Compare commits
240 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 |
|
@ -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
|
||||||
|
)
|
||||||
|
|
|
@ -4,7 +4,7 @@ Oscar64 is a C/C++ cross compiler running on a modern system (such as a Windows
|
||||||
|
|
||||||
The purpose of this compiler is to eliminate the need to write 6502 assembler code to achieve high code density and fast execution speed. It continues to improve with all the games, demos and tools written by it. It supports disk overlays and banked cartridges for larger projects.
|
The purpose of this compiler is to eliminate the need to write 6502 assembler code to achieve high code density and fast execution speed. It continues to improve with all the games, demos and tools written by it. It supports disk overlays and banked cartridges for larger projects.
|
||||||
|
|
||||||
The C64 executes 418 dhrystone V2.2 iteration per second, when compiled with Oscar64 and -O3 (which shows that the ancient dhrystone benchmark is no match to an optimizing compiler).
|
The C64 executes 442 dhrystone V2.2 iteration per second, when compiled with Oscar64 and -O3 (which shows that the ancient dhrystone benchmark is no match to an optimizing compiler).
|
||||||
|
|
||||||
[Full reference manual](oscar64.md)
|
[Full reference manual](oscar64.md)
|
||||||
[Additional samples and tutorials](https://github.com/drmortalwombat/OscarTutorials)
|
[Additional samples and tutorials](https://github.com/drmortalwombat/OscarTutorials)
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
rem @echo off
|
rem @echo off
|
||||||
|
|
||||||
|
@call :test rolrortest.cpp
|
||||||
|
@if %errorlevel% neq 0 goto :error
|
||||||
|
|
||||||
@call :test bitfields.cpp
|
@call :test bitfields.cpp
|
||||||
@if %errorlevel% neq 0 goto :error
|
@if %errorlevel% neq 0 goto :error
|
||||||
|
|
||||||
|
@ -15,6 +18,9 @@ rem @echo off
|
||||||
@call :testh opp_vector.cpp
|
@call :testh opp_vector.cpp
|
||||||
@if %errorlevel% neq 0 goto :error
|
@if %errorlevel% neq 0 goto :error
|
||||||
|
|
||||||
|
@call :testh opp_static_vector.cpp
|
||||||
|
@if %errorlevel% neq 0 goto :error
|
||||||
|
|
||||||
@call :testh opp_vector_string.cpp
|
@call :testh opp_vector_string.cpp
|
||||||
@if %errorlevel% neq 0 goto :error
|
@if %errorlevel% neq 0 goto :error
|
||||||
|
|
||||||
|
@ -33,7 +39,7 @@ rem @echo off
|
||||||
@call :testh opp_list.cpp
|
@call :testh opp_list.cpp
|
||||||
@if %errorlevel% neq 0 goto :error
|
@if %errorlevel% neq 0 goto :error
|
||||||
|
|
||||||
@call :testh opp_functional.cpp
|
@call :testn opp_functional.cpp
|
||||||
@if %errorlevel% neq 0 goto :error
|
@if %errorlevel% neq 0 goto :error
|
||||||
|
|
||||||
@call :testh operatoroverload.cpp
|
@call :testh operatoroverload.cpp
|
||||||
|
@ -51,7 +57,7 @@ rem @echo off
|
||||||
@call :testh constructortest.cpp
|
@call :testh constructortest.cpp
|
||||||
@if %errorlevel% neq 0 goto :error
|
@if %errorlevel% neq 0 goto :error
|
||||||
|
|
||||||
@call :testh copyconstructor.cpp
|
@call :testn copyconstructor.cpp
|
||||||
@if %errorlevel% neq 0 goto :error
|
@if %errorlevel% neq 0 goto :error
|
||||||
|
|
||||||
@call :testh copyassign.cpp
|
@call :testh copyassign.cpp
|
||||||
|
@ -274,6 +280,15 @@ exit /b %errorlevel%
|
||||||
..\bin\oscar64 -e -O2 -n -dHEAPCHECK %~1
|
..\bin\oscar64 -e -O2 -n -dHEAPCHECK %~1
|
||||||
@if %errorlevel% neq 0 goto :error
|
@if %errorlevel% neq 0 goto :error
|
||||||
|
|
||||||
|
..\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
|
..\bin\oscar64 -e -O0 -bc %~1
|
||||||
@if %errorlevel% neq 0 goto :error
|
@if %errorlevel% neq 0 goto :error
|
||||||
|
|
||||||
|
@ -331,6 +346,12 @@ exit /b %errorlevel%
|
||||||
..\bin\oscar64 -e -O2 -xz -Oz -n %~1
|
..\bin\oscar64 -e -O2 -xz -Oz -n %~1
|
||||||
@if %errorlevel% neq 0 goto :error
|
@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
|
@exit /b 0
|
||||||
|
|
||||||
:testb
|
:testb
|
||||||
|
@ -370,4 +391,10 @@ exit /b %errorlevel%
|
||||||
..\bin\oscar64 -e -O2 -xz -Oz -n %~1
|
..\bin\oscar64 -e -O2 -xz -Oz -n %~1
|
||||||
@if %errorlevel% neq 0 goto :error
|
@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
|
@exit /b 0
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
int t, n;
|
int t, n;
|
||||||
|
|
||||||
|
@ -161,7 +162,7 @@ void test_return_value(void)
|
||||||
C2 c(test_ret_v());
|
C2 c(test_ret_v());
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(n == 4 && t == 0);
|
assert(n == 6 && t == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_return_reference(void)
|
void test_return_reference(void)
|
||||||
|
@ -184,7 +185,7 @@ void test_retparam_value(void)
|
||||||
test_param_fv(test_ret_v());
|
test_param_fv(test_ret_v());
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(n == 4 && t == 0);
|
assert(n == 6 && t == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_retparam_reference(void)
|
void test_retparam_reference(void)
|
||||||
|
@ -200,7 +201,6 @@ void test_retparam_reference(void)
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
test_dcopy_init();
|
test_dcopy_init();
|
||||||
test_copy_init();
|
test_copy_init();
|
||||||
test_minit();
|
test_minit();
|
||||||
|
@ -208,9 +208,8 @@ int main(void)
|
||||||
test_param_value();
|
test_param_value();
|
||||||
test_param_ref();
|
test_param_ref();
|
||||||
test_return_value();
|
test_return_value();
|
||||||
#endif
|
|
||||||
test_retparam_value();
|
test_retparam_value();
|
||||||
// test_retparam_reference();
|
test_retparam_reference();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
|
@ -50,5 +50,11 @@ autorefreturn: autorefreturn.cpp
|
||||||
$(OSCAR64_CC) -e -Os -n $<
|
$(OSCAR64_CC) -e -Os -n $<
|
||||||
$(OSCAR64_CC) -e -O3 -n $<
|
$(OSCAR64_CC) -e -O3 -n $<
|
||||||
|
|
||||||
|
copyconstructor: copyconstructor.cpp
|
||||||
|
$(OSCAR64_CC) -e -O2 -n $<
|
||||||
|
$(OSCAR64_CC) -e -O0 -n $<
|
||||||
|
$(OSCAR64_CC) -e -Os -n $<
|
||||||
|
$(OSCAR64_CC) -e -O3 -n $<
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@$(RM) *.asm *.bcs *.int *.lbl *.map *.prg
|
@$(RM) *.asm *.bcs *.int *.lbl *.map *.prg
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -64,5 +64,15 @@ int main(void)
|
||||||
opp::cout << i << ", ";
|
opp::cout << i << ", ";
|
||||||
opp::cout << "\n";
|
opp::cout << "\n";
|
||||||
|
|
||||||
|
assert(v.size() == 36);
|
||||||
|
assert(v[18] == 60);
|
||||||
|
|
||||||
|
v.assign(42, 11);
|
||||||
|
|
||||||
|
assert(v.size() == 42);
|
||||||
|
assert(v[0] == 11);
|
||||||
|
assert(v[15] == 11);
|
||||||
|
assert(v[41] == 11);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -63,6 +63,33 @@ bool nge(long a, long b)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
inline bool ieq(long a, long b)
|
||||||
|
{
|
||||||
|
return a == b;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool ilt(long a, long b)
|
||||||
|
{
|
||||||
|
return a < b;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool igt(long a, long b)
|
||||||
|
{
|
||||||
|
return a > b;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool ile(long a, long b)
|
||||||
|
{
|
||||||
|
return a <= b;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool ige(long a, long b)
|
||||||
|
{
|
||||||
|
return a >= b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool beqz(long a)
|
bool beqz(long a)
|
||||||
{
|
{
|
||||||
return a == 0;
|
return a == 0;
|
||||||
|
@ -188,7 +215,71 @@ bool nge1(long a)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cmp(long a, long b)
|
bool beqm(long a)
|
||||||
|
{
|
||||||
|
return a == -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bltm(long a)
|
||||||
|
{
|
||||||
|
return a < -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bgtm(long a)
|
||||||
|
{
|
||||||
|
return a > -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool blem(long a)
|
||||||
|
{
|
||||||
|
return a <= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bgem(long a)
|
||||||
|
{
|
||||||
|
return a >= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool neqm(long a)
|
||||||
|
{
|
||||||
|
return a == -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma native(neqm)
|
||||||
|
|
||||||
|
bool nltm(long a)
|
||||||
|
{
|
||||||
|
return a < -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma native(nltm)
|
||||||
|
|
||||||
|
bool ngtm(long a)
|
||||||
|
{
|
||||||
|
return a > -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma native(ngtm)
|
||||||
|
|
||||||
|
bool nlem(long a)
|
||||||
|
{
|
||||||
|
return a <= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma native(nlem)
|
||||||
|
|
||||||
|
bool ngem(long a)
|
||||||
|
{
|
||||||
|
return a >= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma native(ngem)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cmpc(long a, long b)
|
||||||
{
|
{
|
||||||
bool beqf = beq(a, b), bltf = blt(a, b), bgtf = bgt(a, b), blef = ble(a, b), bgef = bge(a, b);
|
bool beqf = beq(a, b), bltf = blt(a, b), bgtf = bgt(a, b), blef = ble(a, b), bgef = bge(a, b);
|
||||||
bool neqf = neq(a, b), nltf = nlt(a, b), ngtf = ngt(a, b), nlef = nle(a, b), ngef = nge(a, b);
|
bool neqf = neq(a, b), nltf = nlt(a, b), ngtf = ngt(a, b), nlef = nle(a, b), ngef = nge(a, b);
|
||||||
|
@ -203,6 +294,27 @@ void cmp(long a, long b)
|
||||||
assert(bgef == ngef);
|
assert(bgef == ngef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cmpi(long a, long b)
|
||||||
|
{
|
||||||
|
bool ieqf = ieq(a, b), iltf = ilt(a, b), igtf = igt(a, b), ilef = ile(a, b), igef = ige(a, b);
|
||||||
|
bool neqf = neq(a, b), nltf = nlt(a, b), ngtf = ngt(a, b), nlef = nle(a, b), ngef = nge(a, b);
|
||||||
|
|
||||||
|
printf("INLINE %ld, %ld : EQ %d LT %d GT %d\r", a, b, ieqf, iltf, igtf);
|
||||||
|
printf("NATIVE %ld, %ld : EQ %d LT %d GT %d\r", a, b, neqf, nltf, ngtf);
|
||||||
|
|
||||||
|
assert(ieqf == neqf);
|
||||||
|
assert(iltf == nltf);
|
||||||
|
assert(igtf == ngtf);
|
||||||
|
assert(ilef == nlef);
|
||||||
|
assert(igef == ngef);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmp(long a, long b)
|
||||||
|
{
|
||||||
|
cmpc(a, b);
|
||||||
|
cmpi(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
void cmpz(long a)
|
void cmpz(long a)
|
||||||
{
|
{
|
||||||
bool beqf = beqz(a), bltf = bltz(a), bgtf = bgtz(a), blef = blez(a), bgef = bgez(a);
|
bool beqf = beqz(a), bltf = bltz(a), bgtf = bgtz(a), blef = blez(a), bgef = bgez(a);
|
||||||
|
@ -233,6 +345,21 @@ void cmp1(long a)
|
||||||
assert(bgef == ngef);
|
assert(bgef == ngef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cmpm(long a)
|
||||||
|
{
|
||||||
|
bool beqf = beqm(a), bltf = bltm(a), bgtf = bgtm(a), blef = blem(a), bgef = bgem(a);
|
||||||
|
bool neqf = neqm(a), nltf = nltm(a), ngtf = ngtm(a), nlef = nlem(a), ngef = ngem(a);
|
||||||
|
|
||||||
|
printf("BYTE %ld, 1 : EQ %d LT %d GT %d LE %d GE %d\r", a, beqf, bltf, bgtf, blef, bgef);
|
||||||
|
printf("NATIVE %ld, 1 : EQ %d LT %d GT %d LE %d GE %d\r", a, neqf, nltf, ngtf, nlef, ngef);
|
||||||
|
|
||||||
|
assert(beqf == neqf);
|
||||||
|
assert(bltf == nltf);
|
||||||
|
assert(bgtf == ngtf);
|
||||||
|
assert(blef == nlef);
|
||||||
|
assert(bgef == ngef);
|
||||||
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
cmp( 0, 1);
|
cmp( 0, 1);
|
||||||
|
@ -327,6 +454,10 @@ int main(void)
|
||||||
cmp1(256);
|
cmp1(256);
|
||||||
cmp1(10000);
|
cmp1(10000);
|
||||||
cmp1(20000);
|
cmp1(20000);
|
||||||
|
cmp1(1000000l);
|
||||||
|
cmp1(2000000l);
|
||||||
|
cmp1(100000000l);
|
||||||
|
cmp1(200000000l);
|
||||||
cmp1(-1);
|
cmp1(-1);
|
||||||
cmp1(-2);
|
cmp1(-2);
|
||||||
cmp1(-3);
|
cmp1(-3);
|
||||||
|
@ -334,6 +465,34 @@ int main(void)
|
||||||
cmp1(-256);
|
cmp1(-256);
|
||||||
cmp1(-10000);
|
cmp1(-10000);
|
||||||
cmp1(-20000);
|
cmp1(-20000);
|
||||||
|
cmp1(-1000000l);
|
||||||
|
cmp1(-2000000l);
|
||||||
|
cmp1(-100000000l);
|
||||||
|
cmp1(-200000000l);
|
||||||
|
|
||||||
|
cmpm(0);
|
||||||
|
cmpm(1);
|
||||||
|
cmpm(2);
|
||||||
|
cmpm(3);
|
||||||
|
cmpm(255);
|
||||||
|
cmpm(256);
|
||||||
|
cmpm(10000);
|
||||||
|
cmpm(20000);
|
||||||
|
cmpm(1000000l);
|
||||||
|
cmpm(2000000l);
|
||||||
|
cmpm(100000000l);
|
||||||
|
cmpm(200000000l);
|
||||||
|
cmpm(-1);
|
||||||
|
cmpm(-2);
|
||||||
|
cmpm(-3);
|
||||||
|
cmpm(-255);
|
||||||
|
cmpm(-256);
|
||||||
|
cmpm(-10000);
|
||||||
|
cmpm(-20000);
|
||||||
|
cmpm(-1000000l);
|
||||||
|
cmpm(-2000000l);
|
||||||
|
cmpm(-100000000l);
|
||||||
|
cmpm(-200000000l);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ enum SIDFXState
|
||||||
SIDFX_WAIT
|
SIDFX_WAIT
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct SIDFXChannel
|
__striped static struct SIDFXChannel
|
||||||
{
|
{
|
||||||
const SIDFX * volatile com;
|
const SIDFX * volatile com;
|
||||||
byte delay, priority;
|
byte delay, priority;
|
||||||
|
@ -27,6 +27,7 @@ void sidfx_init(void)
|
||||||
channels[i].com = nullptr;
|
channels[i].com = nullptr;
|
||||||
channels[i].state = SIDFX_IDLE;
|
channels[i].state = SIDFX_IDLE;
|
||||||
channels[i].priority = 0;
|
channels[i].priority = 0;
|
||||||
|
channels[i].delay = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +36,11 @@ bool sidfx_idle(byte chn)
|
||||||
return channels[chn].state == SIDFX_IDLE;
|
return channels[chn].state == SIDFX_IDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char sidfx_cnt(byte chn)
|
||||||
|
{
|
||||||
|
return channels[chn].cnt;
|
||||||
|
}
|
||||||
|
|
||||||
void sidfx_play(byte chn, const SIDFX * fx, byte cnt)
|
void sidfx_play(byte chn, const SIDFX * fx, byte cnt)
|
||||||
{
|
{
|
||||||
SIDFXState ns = channels[chn].state;
|
SIDFXState ns = channels[chn].state;
|
||||||
|
@ -47,6 +53,7 @@ void sidfx_play(byte chn, const SIDFX * fx, byte cnt)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
channels[chn].state = SIDFX_IDLE;
|
channels[chn].state = SIDFX_IDLE;
|
||||||
|
channels[chn].delay = 1;
|
||||||
|
|
||||||
channels[chn].com = fx;
|
channels[chn].com = fx;
|
||||||
channels[chn].cnt = cnt - 1;
|
channels[chn].cnt = cnt - 1;
|
||||||
|
@ -59,30 +66,58 @@ void sidfx_stop(byte chn)
|
||||||
{
|
{
|
||||||
channels[chn].com = nullptr;
|
channels[chn].com = nullptr;
|
||||||
if (channels[chn].state != SIDFX_IDLE)
|
if (channels[chn].state != SIDFX_IDLE)
|
||||||
|
{
|
||||||
channels[chn].state = SIDFX_RESET_0;
|
channels[chn].state = SIDFX_RESET_0;
|
||||||
|
channels[chn].delay = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sidfx_loop_ch(byte ch)
|
inline void sidfx_loop_ch(byte ch)
|
||||||
{
|
{
|
||||||
|
if (channels[ch].state)
|
||||||
|
{
|
||||||
|
const SIDFX * com = channels[ch].com;
|
||||||
|
|
||||||
|
channels[ch].delay--;
|
||||||
|
if (channels[ch].delay)
|
||||||
|
{
|
||||||
|
if (com->dfreq)
|
||||||
|
{
|
||||||
|
channels[ch].freq += com->dfreq;
|
||||||
|
sid.voices[ch].freq = channels[ch].freq;
|
||||||
|
}
|
||||||
|
if (com->dpwm)
|
||||||
|
{
|
||||||
|
channels[ch].pwm += com->dpwm;
|
||||||
|
sid.voices[ch].pwm = channels[ch].pwm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!channels[ch].delay)
|
||||||
|
{
|
||||||
switch (channels[ch].state)
|
switch (channels[ch].state)
|
||||||
{
|
{
|
||||||
case SIDFX_IDLE:
|
case SIDFX_IDLE:
|
||||||
|
channels[ch].delay = 1;
|
||||||
break;
|
break;
|
||||||
case SIDFX_RESET_0:
|
case SIDFX_RESET_0:
|
||||||
sid.voices[ch].ctrl = 0;
|
sid.voices[ch].ctrl = 0;
|
||||||
sid.voices[ch].attdec = 0;
|
sid.voices[ch].attdec = 0;
|
||||||
sid.voices[ch].susrel = 0;
|
sid.voices[ch].susrel = 0;
|
||||||
|
if (com)
|
||||||
channels[ch].state = SIDFX_READY;
|
channels[ch].state = SIDFX_READY;
|
||||||
|
else
|
||||||
|
channels[ch].state = SIDFX_IDLE;
|
||||||
|
channels[ch].delay = 1;
|
||||||
break;
|
break;
|
||||||
case SIDFX_RESET_1:
|
case SIDFX_RESET_1:
|
||||||
sid.voices[ch].ctrl = SID_CTRL_TEST;
|
sid.voices[ch].ctrl = SID_CTRL_TEST;
|
||||||
|
sid.voices[ch].ctrl = 0;
|
||||||
|
sid.voices[ch].attdec = 0;
|
||||||
|
sid.voices[ch].susrel = 0;
|
||||||
channels[ch].state = SIDFX_READY;
|
channels[ch].state = SIDFX_READY;
|
||||||
break;
|
break;
|
||||||
case SIDFX_READY:
|
case SIDFX_READY:
|
||||||
{
|
|
||||||
const SIDFX * com = channels[ch].com;
|
|
||||||
if (com)
|
|
||||||
{
|
|
||||||
channels[ch].freq = com->freq;
|
channels[ch].freq = com->freq;
|
||||||
channels[ch].pwm = com->pwm;
|
channels[ch].pwm = com->pwm;
|
||||||
|
|
||||||
|
@ -92,38 +127,34 @@ inline void sidfx_loop_ch(byte ch)
|
||||||
sid.voices[ch].susrel = com->susrel;
|
sid.voices[ch].susrel = com->susrel;
|
||||||
sid.voices[ch].ctrl = com->ctrl;
|
sid.voices[ch].ctrl = com->ctrl;
|
||||||
|
|
||||||
|
if (com->ctrl & SID_CTRL_GATE)
|
||||||
|
{
|
||||||
channels[ch].delay = com->time1;
|
channels[ch].delay = com->time1;
|
||||||
channels[ch].state = SIDFX_PLAY;
|
channels[ch].state = SIDFX_PLAY;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
channels[ch].state = SIDFX_IDLE;
|
{
|
||||||
|
channels[ch].delay = com->time0;
|
||||||
|
channels[ch].state = SIDFX_PLAY;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SIDFX_PLAY:
|
case SIDFX_PLAY:
|
||||||
{
|
if (com->time0)
|
||||||
const SIDFX * com = channels[ch].com;
|
|
||||||
if (com->dfreq)
|
|
||||||
{
|
|
||||||
channels[ch].freq += com->dfreq;
|
|
||||||
sid.voices[ch].freq = channels[ch].freq;
|
|
||||||
}
|
|
||||||
if (com->dpwm)
|
|
||||||
{
|
|
||||||
channels[ch].pwm += com->dpwm;
|
|
||||||
sid.voices[ch].pwm = channels[ch].pwm;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (channels[ch].delay)
|
|
||||||
channels[ch].delay--;
|
|
||||||
else if (com->time0)
|
|
||||||
{
|
{
|
||||||
sid.voices[ch].ctrl = com->ctrl & ~SID_CTRL_GATE;
|
sid.voices[ch].ctrl = com->ctrl & ~SID_CTRL_GATE;
|
||||||
channels[ch].delay = com->time0;
|
channels[ch].delay = com->time0 - 1;
|
||||||
channels[ch].state = SIDFX_WAIT;
|
channels[ch].state = SIDFX_WAIT;
|
||||||
}
|
}
|
||||||
else if (channels[ch].cnt)
|
else if (channels[ch].cnt)
|
||||||
{
|
{
|
||||||
|
char sr = com->susrel & 0xf0;
|
||||||
com++;
|
com++;
|
||||||
|
char ctrl = com->ctrl;
|
||||||
|
if ((com->attdec & 0xef) == 0 && (ctrl & SID_CTRL_GATE) && (com->susrel & 0xf0) > sr)
|
||||||
|
{
|
||||||
|
sid.voices[ch].ctrl = ctrl & ~SID_CTRL_GATE;
|
||||||
|
sid.voices[ch].ctrl = ctrl | SID_CTRL_GATE;
|
||||||
|
}
|
||||||
channels[ch].cnt--;
|
channels[ch].cnt--;
|
||||||
channels[ch].com = com;
|
channels[ch].com = com;
|
||||||
channels[ch].priority = com->priority;
|
channels[ch].priority = com->priority;
|
||||||
|
@ -131,46 +162,31 @@ inline void sidfx_loop_ch(byte ch)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
channels[ch].com = nullptr;
|
com = nullptr;
|
||||||
channels[ch].state = SIDFX_RESET_0;
|
channels[ch].state = SIDFX_RESET_0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case SIDFX_WAIT:
|
case SIDFX_WAIT:
|
||||||
{
|
if (channels[ch].cnt)
|
||||||
const SIDFX * com = channels[ch].com;
|
|
||||||
if (com->dfreq)
|
|
||||||
{
|
|
||||||
channels[ch].freq += com->dfreq;
|
|
||||||
sid.voices[ch].freq = channels[ch].freq;
|
|
||||||
}
|
|
||||||
if (com->dpwm)
|
|
||||||
{
|
|
||||||
channels[ch].pwm += com->dpwm;
|
|
||||||
sid.voices[ch].pwm = channels[ch].pwm;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (channels[ch].delay)
|
|
||||||
channels[ch].delay--;
|
|
||||||
else if (channels[ch].cnt)
|
|
||||||
{
|
{
|
||||||
com++;
|
com++;
|
||||||
channels[ch].cnt--;
|
channels[ch].cnt--;
|
||||||
channels[ch].com = com;
|
channels[ch].com = com;
|
||||||
channels[ch].priority = com->priority;
|
channels[ch].priority = com->priority;
|
||||||
if (com->time0)
|
if (com->ctrl & SID_CTRL_GATE)
|
||||||
channels[ch].state = SIDFX_RESET_0;
|
channels[ch].state = SIDFX_RESET_0;
|
||||||
else
|
else
|
||||||
channels[ch].state = SIDFX_READY;
|
channels[ch].state = SIDFX_READY;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
channels[ch].com = nullptr;
|
com = nullptr;
|
||||||
channels[ch].state = SIDFX_RESET_0;
|
channels[ch].state = SIDFX_RESET_0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sidfx_loop_2(void)
|
void sidfx_loop_2(void)
|
||||||
|
|
|
@ -20,6 +20,8 @@ inline void sidfx_play(byte chn, const SIDFX * fx, byte cnt);
|
||||||
|
|
||||||
void sidfx_stop(byte chn);
|
void sidfx_stop(byte chn);
|
||||||
|
|
||||||
|
char sidfx_cnt(byte chn);
|
||||||
|
|
||||||
void sidfx_loop(void);
|
void sidfx_loop(void);
|
||||||
|
|
||||||
void sidfx_loop_2(void);
|
void sidfx_loop_2(void);
|
||||||
|
|
|
@ -69,7 +69,7 @@ BANKINLINE bool krnio_open(char fnum, char device, char channel)
|
||||||
{
|
{
|
||||||
krnio_pstatus[fnum] = KRNIO_OK;
|
krnio_pstatus[fnum] = KRNIO_OK;
|
||||||
|
|
||||||
return __asm
|
return char(__asm
|
||||||
{
|
{
|
||||||
lda #0
|
lda #0
|
||||||
sta accu
|
sta accu
|
||||||
|
@ -94,8 +94,7 @@ BANKINLINE bool krnio_open(char fnum, char device, char channel)
|
||||||
|
|
||||||
BANKOUT
|
BANKOUT
|
||||||
E2:
|
E2:
|
||||||
};
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma native(krnio_open)
|
#pragma native(krnio_open)
|
||||||
|
@ -131,7 +130,7 @@ BANKINLINE krnioerr krnio_status(void)
|
||||||
|
|
||||||
BANKINLINE bool krnio_load(char fnum, char device, char channel)
|
BANKINLINE bool krnio_load(char fnum, char device, char channel)
|
||||||
{
|
{
|
||||||
return __asm
|
return char(__asm
|
||||||
{
|
{
|
||||||
BANKIN
|
BANKIN
|
||||||
lda fnum
|
lda fnum
|
||||||
|
@ -149,14 +148,14 @@ BANKINLINE bool krnio_load(char fnum, char device, char channel)
|
||||||
rol
|
rol
|
||||||
eor #1
|
eor #1
|
||||||
sta accu
|
sta accu
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma native(krnio_load)
|
#pragma native(krnio_load)
|
||||||
|
|
||||||
BANKINLINE bool krnio_save(char device, const char* start, const char* end)
|
BANKINLINE bool krnio_save(char device, const char* start, const char* end)
|
||||||
{
|
{
|
||||||
return __asm
|
return char(__asm
|
||||||
{
|
{
|
||||||
BANKIN
|
BANKIN
|
||||||
lda #0
|
lda #0
|
||||||
|
@ -175,14 +174,14 @@ BANKINLINE bool krnio_save(char device, const char* start, const char* end)
|
||||||
rol
|
rol
|
||||||
eor #1
|
eor #1
|
||||||
sta accu
|
sta accu
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma native(krnio_save)
|
#pragma native(krnio_save)
|
||||||
|
|
||||||
BANKINLINE bool krnio_chkout(char fnum)
|
BANKINLINE bool krnio_chkout(char fnum)
|
||||||
{
|
{
|
||||||
return __asm
|
return char(__asm
|
||||||
{
|
{
|
||||||
BANKIN
|
BANKIN
|
||||||
ldx fnum
|
ldx fnum
|
||||||
|
@ -193,14 +192,14 @@ BANKINLINE bool krnio_chkout(char fnum)
|
||||||
rol
|
rol
|
||||||
eor #1
|
eor #1
|
||||||
sta accu
|
sta accu
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma native(krnio_chkout)
|
#pragma native(krnio_chkout)
|
||||||
|
|
||||||
BANKINLINE bool krnio_chkin(char fnum)
|
BANKINLINE bool krnio_chkin(char fnum)
|
||||||
{
|
{
|
||||||
return __asm
|
return char(__asm
|
||||||
{
|
{
|
||||||
BANKIN
|
BANKIN
|
||||||
ldx fnum
|
ldx fnum
|
||||||
|
@ -211,7 +210,7 @@ BANKINLINE bool krnio_chkin(char fnum)
|
||||||
rol
|
rol
|
||||||
eor #1
|
eor #1
|
||||||
sta accu
|
sta accu
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma native(krnio_chkin)
|
#pragma native(krnio_chkin)
|
||||||
|
@ -230,14 +229,14 @@ BANKINLINE void krnio_clrchn(void)
|
||||||
|
|
||||||
BANKINLINE bool krnio_chrout(char ch)
|
BANKINLINE bool krnio_chrout(char ch)
|
||||||
{
|
{
|
||||||
return __asm
|
return char(__asm
|
||||||
{
|
{
|
||||||
BANKIN
|
BANKIN
|
||||||
lda ch
|
lda ch
|
||||||
jsr $ffd2 // chrout
|
jsr $ffd2 // chrout
|
||||||
sta accu
|
sta accu
|
||||||
BANKOUT
|
BANKOUT
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma native(krnio_chrout)
|
#pragma native(krnio_chrout)
|
||||||
|
@ -422,7 +421,7 @@ int krnio_gets(char fnum, char * data, int num)
|
||||||
|
|
||||||
if (krnio_chkin(fnum))
|
if (krnio_chkin(fnum))
|
||||||
{
|
{
|
||||||
krnioerr err;
|
krnioerr err = KRNIO_OK;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int ch;
|
int ch;
|
||||||
while (i + 1 < num)
|
while (i + 1 < num)
|
||||||
|
|
|
@ -5,16 +5,16 @@
|
||||||
#include <c64/asm6502.h>
|
#include <c64/asm6502.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
volatile char npos = 1, tpos = 0;
|
|
||||||
volatile byte rirq_count;
|
volatile byte rirq_count;
|
||||||
|
static byte rirq_pcount;
|
||||||
|
|
||||||
byte rasterIRQRows[NUM_IRQS + 1];
|
byte rasterIRQRows[NUM_IRQS + 1];
|
||||||
byte rasterIRQIndex[NUM_IRQS + 1];
|
byte rasterIRQIndex[NUM_IRQS + 1]; // Sort order of interrupt index, offset by one
|
||||||
#ifdef ZPAGE_IRQS
|
#ifdef ZPAGE_IRQS
|
||||||
__zeropage
|
__zeropage
|
||||||
#endif
|
#endif
|
||||||
byte rasterIRQNext[NUM_IRQS + 1];
|
byte rasterIRQNext[NUM_IRQS + 1]; // Rasterline of interrupt, terminated by 0xff
|
||||||
byte rasterIRQLow[NUM_IRQS];
|
byte rasterIRQLow[NUM_IRQS]; // Address of interrupt code
|
||||||
byte rasterIRQHigh[NUM_IRQS];
|
byte rasterIRQHigh[NUM_IRQS];
|
||||||
|
|
||||||
#ifdef ZPAGE_IRQS
|
#ifdef ZPAGE_IRQS
|
||||||
|
@ -22,28 +22,25 @@ __zeropage
|
||||||
#endif
|
#endif
|
||||||
byte nextIRQ;
|
byte nextIRQ;
|
||||||
|
|
||||||
__asm irq0
|
// nextIRQ is the index of the next expected IRQ, or $ff if no IRQ is scheduled
|
||||||
|
|
||||||
|
__asm rirq_isr_ram_io
|
||||||
{
|
{
|
||||||
pha
|
stx plrx + 1
|
||||||
txa
|
|
||||||
pha
|
|
||||||
tya
|
|
||||||
pha
|
|
||||||
kentry:
|
|
||||||
asl $d019
|
|
||||||
|
|
||||||
ldx nextIRQ
|
ldx nextIRQ
|
||||||
|
bmi exi
|
||||||
|
|
||||||
|
sta plra + 1
|
||||||
|
sty plry + 1
|
||||||
|
|
||||||
l1:
|
l1:
|
||||||
lda rasterIRQNext, x
|
lda rasterIRQNext, x
|
||||||
cmp #$ff
|
|
||||||
beq e1
|
|
||||||
|
|
||||||
ldy rasterIRQIndex + 1, x
|
ldy rasterIRQIndex + 1, x
|
||||||
tax
|
ldx rasterIRQLow, y
|
||||||
lda rasterIRQLow, y
|
stx ji + 1
|
||||||
sta ji + 1
|
ldx rasterIRQHigh, y
|
||||||
lda rasterIRQHigh, y
|
stx ji + 2
|
||||||
sta ji + 2
|
|
||||||
|
|
||||||
ji:
|
ji:
|
||||||
jsr $0000
|
jsr $0000
|
||||||
|
@ -51,21 +48,82 @@ ji:
|
||||||
inc nextIRQ
|
inc nextIRQ
|
||||||
ldx nextIRQ
|
ldx nextIRQ
|
||||||
|
|
||||||
lda rasterIRQNext, x
|
ldy rasterIRQNext, x
|
||||||
cmp #$ff
|
|
||||||
beq e2
|
|
||||||
// carry is cleared at this point
|
|
||||||
|
|
||||||
tay
|
asl $d019
|
||||||
sbc #2
|
|
||||||
cmp $d012
|
cpy #$ff
|
||||||
|
beq e2
|
||||||
|
|
||||||
|
dey
|
||||||
|
sty $d012
|
||||||
|
dey
|
||||||
|
cpy $d012
|
||||||
|
bcc l1
|
||||||
|
|
||||||
|
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
|
bcc l1
|
||||||
|
|
||||||
exd:
|
exd:
|
||||||
dey
|
|
||||||
ex:
|
|
||||||
sty $d012
|
|
||||||
|
|
||||||
pla
|
pla
|
||||||
tay
|
tay
|
||||||
pla
|
pla
|
||||||
|
@ -73,25 +131,22 @@ ex:
|
||||||
pla
|
pla
|
||||||
rti
|
rti
|
||||||
|
|
||||||
e2:
|
exi:
|
||||||
|
asl $d019
|
||||||
ldx npos
|
|
||||||
stx tpos
|
|
||||||
inc rirq_count
|
|
||||||
tay
|
|
||||||
|
|
||||||
bit $d011
|
|
||||||
bpl ex
|
|
||||||
|
|
||||||
e1:
|
|
||||||
ldx #0
|
|
||||||
stx nextIRQ
|
|
||||||
ldy rasterIRQNext
|
|
||||||
jmp exd
|
jmp exd
|
||||||
|
|
||||||
|
e2:
|
||||||
|
inc rirq_count
|
||||||
|
|
||||||
|
ldy rasterIRQNext
|
||||||
|
dey
|
||||||
|
sty $d012
|
||||||
|
ldx #0
|
||||||
|
stx nextIRQ
|
||||||
|
beq exd
|
||||||
}
|
}
|
||||||
|
|
||||||
__asm irq2
|
__asm rirq_isr_noio
|
||||||
{
|
{
|
||||||
pha
|
pha
|
||||||
txa
|
txa
|
||||||
|
@ -105,20 +160,15 @@ kentry:
|
||||||
lda #$35
|
lda #$35
|
||||||
sta $01
|
sta $01
|
||||||
|
|
||||||
asl $d019
|
|
||||||
|
|
||||||
ldx nextIRQ
|
ldx nextIRQ
|
||||||
|
bmi exi
|
||||||
l1:
|
l1:
|
||||||
lda rasterIRQNext, x
|
lda rasterIRQNext, x
|
||||||
cmp #$ff
|
|
||||||
beq e1
|
|
||||||
|
|
||||||
ldy rasterIRQIndex + 1, x
|
ldy rasterIRQIndex + 1, x
|
||||||
tax
|
ldx rasterIRQLow, y
|
||||||
lda rasterIRQLow, y
|
stx ji + 1
|
||||||
sta ji + 1
|
ldx rasterIRQHigh, y
|
||||||
lda rasterIRQHigh, y
|
stx ji + 2
|
||||||
sta ji + 2
|
|
||||||
|
|
||||||
ji:
|
ji:
|
||||||
jsr $0000
|
jsr $0000
|
||||||
|
@ -126,21 +176,20 @@ ji:
|
||||||
inc nextIRQ
|
inc nextIRQ
|
||||||
ldx nextIRQ
|
ldx nextIRQ
|
||||||
|
|
||||||
lda rasterIRQNext, x
|
ldy rasterIRQNext, x
|
||||||
cmp #$ff
|
|
||||||
beq e2
|
asl $d019
|
||||||
// carry is cleared at this point
|
|
||||||
|
cpy #$ff
|
||||||
|
beq e2
|
||||||
|
|
||||||
tay
|
|
||||||
dey
|
dey
|
||||||
sbc #2
|
sty $d012
|
||||||
cmp $d012
|
dey
|
||||||
|
cpy $d012
|
||||||
bcc l1
|
bcc l1
|
||||||
|
|
||||||
sty $d012
|
exd:
|
||||||
|
|
||||||
ex:
|
|
||||||
|
|
||||||
pla
|
pla
|
||||||
sta $01
|
sta $01
|
||||||
|
|
||||||
|
@ -151,45 +200,35 @@ ex:
|
||||||
pla
|
pla
|
||||||
rti
|
rti
|
||||||
|
|
||||||
e2:
|
exi:
|
||||||
|
asl $d019
|
||||||
|
jmp exd
|
||||||
|
|
||||||
ldx npos
|
e2:
|
||||||
stx tpos
|
|
||||||
inc rirq_count
|
inc rirq_count
|
||||||
|
|
||||||
bit $d011
|
|
||||||
bmi e1
|
|
||||||
|
|
||||||
sta $d012
|
|
||||||
jmp ex
|
|
||||||
|
|
||||||
e1:
|
|
||||||
ldx #0
|
|
||||||
stx nextIRQ
|
|
||||||
ldy rasterIRQNext
|
ldy rasterIRQNext
|
||||||
dey
|
dey
|
||||||
sty $d012
|
sty $d012
|
||||||
jmp ex
|
ldx #0
|
||||||
|
stx nextIRQ
|
||||||
|
beq exd
|
||||||
}
|
}
|
||||||
|
|
||||||
__asm irq1
|
__asm rirq_isr_kernal_io
|
||||||
{
|
{
|
||||||
lda $d019
|
lda $d019
|
||||||
bpl ex2
|
bpl ex2
|
||||||
|
|
||||||
ldx nextIRQ
|
ldx nextIRQ
|
||||||
|
bmi exi
|
||||||
l1:
|
l1:
|
||||||
lda rasterIRQNext, x
|
lda rasterIRQNext, x
|
||||||
cmp #$ff
|
|
||||||
beq e1
|
|
||||||
|
|
||||||
ldy rasterIRQIndex + 1, x
|
ldy rasterIRQIndex + 1, x
|
||||||
tax
|
ldx rasterIRQLow, y
|
||||||
lda rasterIRQLow, y
|
stx ji + 1
|
||||||
sta ji + 1
|
ldx rasterIRQHigh, y
|
||||||
lda rasterIRQHigh, y
|
stx ji + 2
|
||||||
sta ji + 2
|
|
||||||
|
|
||||||
ji:
|
ji:
|
||||||
jsr $0000
|
jsr $0000
|
||||||
|
@ -198,45 +237,36 @@ jx:
|
||||||
inc nextIRQ
|
inc nextIRQ
|
||||||
ldx nextIRQ
|
ldx nextIRQ
|
||||||
|
|
||||||
lda rasterIRQNext, x
|
ldy rasterIRQNext, x
|
||||||
cmp #$ff
|
|
||||||
beq e2
|
|
||||||
|
|
||||||
tay
|
|
||||||
|
|
||||||
sec
|
|
||||||
sbc #4
|
|
||||||
cmp $d012
|
|
||||||
bcc l1
|
|
||||||
|
|
||||||
dey
|
|
||||||
sty $d012
|
|
||||||
w1:
|
|
||||||
jmp ex
|
|
||||||
|
|
||||||
e2:
|
|
||||||
ldx npos
|
|
||||||
stx tpos
|
|
||||||
inc rirq_count
|
|
||||||
|
|
||||||
bit $d011
|
|
||||||
bmi e1
|
|
||||||
|
|
||||||
sta $d012
|
|
||||||
|
|
||||||
jmp ex
|
|
||||||
|
|
||||||
e1:
|
|
||||||
ldx #0
|
|
||||||
stx nextIRQ
|
|
||||||
lda rasterIRQNext, x
|
|
||||||
sec
|
|
||||||
sbc #1
|
|
||||||
sta $d012
|
|
||||||
|
|
||||||
ex:
|
|
||||||
asl $d019
|
asl $d019
|
||||||
|
|
||||||
|
cpy #$ff
|
||||||
|
beq e2
|
||||||
|
|
||||||
|
dey
|
||||||
|
dey
|
||||||
|
sty $d012
|
||||||
|
dey
|
||||||
|
cpy $d012
|
||||||
|
bcc l1
|
||||||
|
|
||||||
|
exd:
|
||||||
|
jmp $ea81
|
||||||
|
|
||||||
|
exi:
|
||||||
|
asl $d019
|
||||||
|
jmp $ea81
|
||||||
|
|
||||||
|
e2:
|
||||||
|
inc rirq_count
|
||||||
|
|
||||||
|
ldy rasterIRQNext
|
||||||
|
dey
|
||||||
|
dey
|
||||||
|
sty $d012
|
||||||
|
ldx #0
|
||||||
|
stx nextIRQ
|
||||||
jmp $ea81
|
jmp $ea81
|
||||||
|
|
||||||
ex2:
|
ex2:
|
||||||
|
@ -245,7 +275,7 @@ ex2:
|
||||||
jmp $ea31
|
jmp $ea31
|
||||||
}
|
}
|
||||||
|
|
||||||
__asm irq3
|
__asm rirq_isr_kernal_noio
|
||||||
{
|
{
|
||||||
lda $01
|
lda $01
|
||||||
pha
|
pha
|
||||||
|
@ -256,17 +286,14 @@ __asm irq3
|
||||||
bpl ex2
|
bpl ex2
|
||||||
|
|
||||||
ldx nextIRQ
|
ldx nextIRQ
|
||||||
|
bmi exi
|
||||||
l1:
|
l1:
|
||||||
lda rasterIRQNext, x
|
lda rasterIRQNext, x
|
||||||
cmp #$ff
|
|
||||||
beq e1
|
|
||||||
|
|
||||||
ldy rasterIRQIndex + 1, x
|
ldy rasterIRQIndex + 1, x
|
||||||
tax
|
ldx rasterIRQLow, y
|
||||||
lda rasterIRQLow, y
|
stx ji + 1
|
||||||
sta ji + 1
|
ldx rasterIRQHigh, y
|
||||||
lda rasterIRQHigh, y
|
stx ji + 2
|
||||||
sta ji + 2
|
|
||||||
|
|
||||||
ji:
|
ji:
|
||||||
jsr $0000
|
jsr $0000
|
||||||
|
@ -275,49 +302,40 @@ jx:
|
||||||
inc nextIRQ
|
inc nextIRQ
|
||||||
ldx nextIRQ
|
ldx nextIRQ
|
||||||
|
|
||||||
lda rasterIRQNext, x
|
ldy rasterIRQNext, x
|
||||||
cmp #$ff
|
|
||||||
|
asl $d019
|
||||||
|
|
||||||
|
cpy #$ff
|
||||||
beq e2
|
beq e2
|
||||||
|
|
||||||
tay
|
dey
|
||||||
|
|
||||||
sec
|
|
||||||
sbc #4
|
|
||||||
cmp $d012
|
|
||||||
bcc l1
|
|
||||||
|
|
||||||
dey
|
dey
|
||||||
sty $d012
|
sty $d012
|
||||||
w1:
|
dey
|
||||||
jmp ex
|
cpy $d012
|
||||||
|
bcc l1
|
||||||
e2:
|
exd:
|
||||||
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
|
|
||||||
pla
|
pla
|
||||||
sta $01
|
sta $01
|
||||||
|
|
||||||
jmp $ea81
|
jmp $ea81
|
||||||
|
|
||||||
|
exi:
|
||||||
|
asl $d019
|
||||||
|
jmp exd
|
||||||
|
|
||||||
|
e2:
|
||||||
|
inc rirq_count
|
||||||
|
|
||||||
|
ldy rasterIRQNext
|
||||||
|
dey
|
||||||
|
dey
|
||||||
|
sty $d012
|
||||||
|
ldx #0
|
||||||
|
stx nextIRQ
|
||||||
|
beq exd
|
||||||
|
|
||||||
ex2:
|
ex2:
|
||||||
LDA $DC0D
|
LDA $DC0D
|
||||||
cli
|
cli
|
||||||
|
@ -347,8 +365,8 @@ void rirq_build(RIRQCode * ic, byte size)
|
||||||
ic->size = size;
|
ic->size = size;
|
||||||
|
|
||||||
asm_im(ic->code + 0, ASM_LDY, 0);
|
asm_im(ic->code + 0, ASM_LDY, 0);
|
||||||
asm_im(ic->code + 2, ASM_LDA, 0);
|
asm_im(ic->code + 2, ASM_LDX, 0);
|
||||||
asm_ab(ic->code + 4, ASM_CPX, 0xd012);
|
asm_ab(ic->code + 4, ASM_CMP, 0xd012);
|
||||||
asm_rl(ic->code + 7, ASM_BCS, -5);
|
asm_rl(ic->code + 7, ASM_BCS, -5);
|
||||||
asm_ab(ic->code + 9, ASM_STY, 0x0000);
|
asm_ab(ic->code + 9, ASM_STY, 0x0000);
|
||||||
|
|
||||||
|
@ -362,7 +380,7 @@ void rirq_build(RIRQCode * ic, byte size)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
asm_ab(ic->code + 12, ASM_STA, 0x0000);
|
asm_ab(ic->code + 12, ASM_STX, 0x0000);
|
||||||
|
|
||||||
byte p = 15;
|
byte p = 15;
|
||||||
for(byte i=2; i<size; i++)
|
for(byte i=2; i<size; i++)
|
||||||
|
@ -482,7 +500,7 @@ void rirq_init_kernal(void)
|
||||||
sei
|
sei
|
||||||
}
|
}
|
||||||
|
|
||||||
*(void **)0x0314 = irq1;
|
*(void **)0x0314 = rirq_isr_kernal_io;
|
||||||
|
|
||||||
vic.intr_enable = 1;
|
vic.intr_enable = 1;
|
||||||
vic.ctrl1 &= 0x7f;
|
vic.ctrl1 &= 0x7f;
|
||||||
|
@ -490,7 +508,7 @@ void rirq_init_kernal(void)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rirq_init_kernal_io(void)
|
void rirq_init_kernal_noio(void)
|
||||||
{
|
{
|
||||||
rirq_init_tables();
|
rirq_init_tables();
|
||||||
|
|
||||||
|
@ -499,7 +517,7 @@ void rirq_init_kernal_io(void)
|
||||||
sei
|
sei
|
||||||
}
|
}
|
||||||
|
|
||||||
*(void **)0x0314 = irq3;
|
*(void **)0x0314 = rirq_isr_kernal_noio;
|
||||||
|
|
||||||
vic.intr_enable = 1;
|
vic.intr_enable = 1;
|
||||||
vic.ctrl1 &= 0x7f;
|
vic.ctrl1 &= 0x7f;
|
||||||
|
@ -516,8 +534,8 @@ void rirq_init_crt(void)
|
||||||
sei
|
sei
|
||||||
}
|
}
|
||||||
|
|
||||||
*(void **)0x0314 = irq0.kentry;
|
*(void **)0x0314 = rirq_isr_io.kentry;
|
||||||
*(void **)0xfffe = irq0;
|
*(void **)0xfffe = rirq_isr_io;
|
||||||
|
|
||||||
vic.intr_enable = 1;
|
vic.intr_enable = 1;
|
||||||
vic.ctrl1 &= 0x7f;
|
vic.ctrl1 &= 0x7f;
|
||||||
|
@ -525,7 +543,7 @@ void rirq_init_crt(void)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rirq_init_crt_io(void)
|
void rirq_init_crt_noio(void)
|
||||||
{
|
{
|
||||||
rirq_init_tables();
|
rirq_init_tables();
|
||||||
|
|
||||||
|
@ -534,8 +552,8 @@ void rirq_init_crt_io(void)
|
||||||
sei
|
sei
|
||||||
}
|
}
|
||||||
|
|
||||||
*(void **)0x0314 = irq2.kentry;
|
*(void **)0x0314 = rirq_isr_noio.kentry;
|
||||||
*(void **)0xfffe = irq2;
|
*(void **)0xfffe = rirq_isr_noio;
|
||||||
|
|
||||||
vic.intr_enable = 1;
|
vic.intr_enable = 1;
|
||||||
vic.ctrl1 &= 0x7f;
|
vic.ctrl1 &= 0x7f;
|
||||||
|
@ -552,7 +570,7 @@ void rirq_init_io(void)
|
||||||
sei
|
sei
|
||||||
}
|
}
|
||||||
|
|
||||||
*(void **)0xfffe = irq0;
|
*(void **)0xfffe = rirq_isr_ram_io;
|
||||||
|
|
||||||
vic.intr_enable = 1;
|
vic.intr_enable = 1;
|
||||||
vic.ctrl1 &= 0x7f;
|
vic.ctrl1 &= 0x7f;
|
||||||
|
@ -569,7 +587,7 @@ void rirq_init_memmap(void)
|
||||||
sei
|
sei
|
||||||
}
|
}
|
||||||
|
|
||||||
*(void **)0xfffe = irq2;
|
*(void **)0xfffe = rirq_isr_noio;
|
||||||
|
|
||||||
vic.intr_enable = 1;
|
vic.intr_enable = 1;
|
||||||
vic.ctrl1 &= 0x7f;
|
vic.ctrl1 &= 0x7f;
|
||||||
|
@ -587,12 +605,18 @@ void rirq_init(bool kernalIRQ)
|
||||||
|
|
||||||
void rirq_wait(void)
|
void rirq_wait(void)
|
||||||
{
|
{
|
||||||
while (tpos != npos) ;
|
char i0 = rirq_pcount;
|
||||||
npos++;
|
char i1;
|
||||||
|
do {
|
||||||
|
i1 = rirq_count;
|
||||||
|
} while (i0 == i1);
|
||||||
|
rirq_pcount = i1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rirq_sort(void)
|
void rirq_sort(bool inirq)
|
||||||
{
|
{
|
||||||
|
// disable raster interrupts while sorting
|
||||||
|
nextIRQ = 0xff;
|
||||||
#if 1
|
#if 1
|
||||||
byte maxr = rasterIRQRows[rasterIRQIndex[1]];
|
byte maxr = rasterIRQRows[rasterIRQIndex[1]];
|
||||||
for(byte i = 2; i<NUM_IRQS + 1; i++)
|
for(byte i = 2; i<NUM_IRQS + 1; i++)
|
||||||
|
@ -640,11 +664,18 @@ void rirq_sort(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
npos++;
|
rirq_pcount = rirq_count;
|
||||||
nextIRQ = 0;
|
if (inirq)
|
||||||
byte yp = rasterIRQNext[nextIRQ];
|
nextIRQ = NUM_IRQS - 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
byte yp = rasterIRQNext[0];
|
||||||
if (yp != 0xff)
|
if (yp != 0xff)
|
||||||
|
{
|
||||||
vic.raster = yp - 1;
|
vic.raster = yp - 1;
|
||||||
|
nextIRQ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rirq_start(void)
|
void rirq_start(void)
|
||||||
|
@ -658,6 +689,7 @@ void rirq_start(void)
|
||||||
lda #100
|
lda #100
|
||||||
sta $d012
|
sta $d012
|
||||||
|
|
||||||
|
asl $d019
|
||||||
cli
|
cli
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,7 +154,7 @@ void rirq_init_kernal(void);
|
||||||
|
|
||||||
// Raster IRQ through kernal, with IO range not always enabled
|
// Raster IRQ through kernal, with IO range not always enabled
|
||||||
// calls kernal continuation
|
// calls kernal continuation
|
||||||
void rirq_init_kernal_io(void);
|
void rirq_init_kernal_noio(void);
|
||||||
|
|
||||||
// Raster IRQ through RAM and ROM vector, with ROM disabled or not and IO range always enabled
|
// Raster IRQ through RAM and ROM vector, with ROM disabled or not and IO range always enabled
|
||||||
// does not call kernal continuation
|
// does not call kernal continuation
|
||||||
|
@ -162,7 +162,7 @@ void rirq_init_crt(void);
|
||||||
|
|
||||||
// Raster IRQ through RAM and ROM vector, with ROM disabled or not and IO range not always enabled
|
// Raster IRQ through RAM and ROM vector, with ROM disabled or not and IO range not always enabled
|
||||||
// does not call kernal continuation
|
// does not call kernal continuation
|
||||||
void rirq_init_crt_io(void);
|
void rirq_init_crt_noio(void);
|
||||||
|
|
||||||
// Raster IRQ through RAM vector, with ROM disabled and IO range always enabled
|
// Raster IRQ through RAM vector, with ROM disabled and IO range always enabled
|
||||||
// does not call kernal continuation
|
// does not call kernal continuation
|
||||||
|
@ -179,8 +179,9 @@ void rirq_start(void);
|
||||||
void rirq_stop(void);
|
void rirq_stop(void);
|
||||||
|
|
||||||
// Sort the raster IRQ, must be performed at the end of the frame after changing
|
// Sort the raster IRQ, must be performed at the end of the frame after changing
|
||||||
// the vertical position of one of the interrupt operatins.
|
// the vertical position of one of the interrupt operations.
|
||||||
void rirq_sort(void);
|
// Set the inirq flag to true when calling this from an interrupt
|
||||||
|
void rirq_sort(bool inirq = false);
|
||||||
|
|
||||||
// Wait for the last raster IRQ op to have completed. Must be called before a
|
// Wait for the last raster IRQ op to have completed. Must be called before a
|
||||||
// sort if the raster IRQ system is active
|
// sort if the raster IRQ system is active
|
||||||
|
|
|
@ -171,6 +171,12 @@ void vspr_init(char * screen)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vspr_shutdown(void)
|
||||||
|
{
|
||||||
|
for(int i=0; i<VSPRITES_MAX - 7; i++)
|
||||||
|
rirq_clear(i);
|
||||||
|
}
|
||||||
|
|
||||||
void vspr_screen(char * screen)
|
void vspr_screen(char * screen)
|
||||||
{
|
{
|
||||||
vspriteScreen = screen + 0x3f8;
|
vspriteScreen = screen + 0x3f8;
|
||||||
|
|
|
@ -68,6 +68,8 @@ inline void spr_expand(char sp, bool xexpand, bool yexpand);
|
||||||
|
|
||||||
void vspr_init(char * screen);
|
void vspr_init(char * screen);
|
||||||
|
|
||||||
|
void vspr_shutdown(void);
|
||||||
|
|
||||||
void vspr_screen(char * screen);
|
void vspr_screen(char * screen);
|
||||||
|
|
||||||
// set one sprite with the given attribute
|
// set one sprite with the given attribute
|
||||||
|
|
|
@ -114,4 +114,21 @@ void vic_waitBelow(int line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vic_waitRange(char below, char above)
|
||||||
|
{
|
||||||
|
while (vic.ctrl1 & VIC_CTRL1_RST8)
|
||||||
|
;
|
||||||
|
|
||||||
|
if (vic.raster >= above)
|
||||||
|
{
|
||||||
|
while (!(vic.ctrl1 & VIC_CTRL1_RST8))
|
||||||
|
;
|
||||||
|
while (vic.ctrl1 & VIC_CTRL1_RST8)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (vic.raster < below)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma native(vic_waitLine)
|
#pragma native(vic_waitLine)
|
||||||
|
|
|
@ -118,6 +118,9 @@ void vic_waitLine(int line);
|
||||||
// wait for beam to be below a line
|
// wait for beam to be below a line
|
||||||
void vic_waitBelow(int line);
|
void vic_waitBelow(int line);
|
||||||
|
|
||||||
|
// wait for beam to be in a given range on screen
|
||||||
|
void vic_waitRange(char below, char above);
|
||||||
|
|
||||||
// reference to the VIC chip
|
// reference to the VIC chip
|
||||||
#define vic (*((struct VIC *)0xd000))
|
#define vic (*((struct VIC *)0xd000))
|
||||||
|
|
||||||
|
|
|
@ -131,6 +131,18 @@ __asm bsinit
|
||||||
lda #147
|
lda #147
|
||||||
jmp $ffd2
|
jmp $ffd2
|
||||||
}
|
}
|
||||||
|
#elif defined(__CBMPET__)
|
||||||
|
#define bsout 0xffd2
|
||||||
|
#define bsin 0xffe4
|
||||||
|
__asm bsplot
|
||||||
|
{
|
||||||
|
/* no equivalent on PET */
|
||||||
|
}
|
||||||
|
__asm bsinit
|
||||||
|
{
|
||||||
|
/* no equivalent on PET */
|
||||||
|
}
|
||||||
|
#define bsget 0xffcf
|
||||||
#else
|
#else
|
||||||
#define bsout 0xffd2
|
#define bsout 0xffd2
|
||||||
#define bsin 0xffe4
|
#define bsin 0xffe4
|
||||||
|
@ -212,11 +224,10 @@ void putpch(char c)
|
||||||
c ^= 0xa0;
|
c ^= 0xa0;
|
||||||
c ^= 0x20;
|
c ^= 0x20;
|
||||||
#else
|
#else
|
||||||
if (c >= 97)
|
|
||||||
c ^= 0x20;
|
c ^= 0x20;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (giocharmap == IOCHM_PETSCII_2)
|
if (giocharmap == IOCHM_PETSCII_1)
|
||||||
c &= 0xdf;
|
c &= 0xdf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -268,11 +279,19 @@ char getpch(void)
|
||||||
|
|
||||||
char kbhit(void)
|
char kbhit(void)
|
||||||
{
|
{
|
||||||
|
#if defined(__CBMPET__)
|
||||||
|
return __asm
|
||||||
|
{
|
||||||
|
lda $9e
|
||||||
|
sta accu
|
||||||
|
};
|
||||||
|
#else
|
||||||
return __asm
|
return __asm
|
||||||
{
|
{
|
||||||
lda $c6
|
lda $c6
|
||||||
sta accu
|
sta accu
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
char getche(void)
|
char getche(void)
|
||||||
|
@ -323,10 +342,7 @@ void putch(char c)
|
||||||
|
|
||||||
void clrscr(void)
|
void clrscr(void)
|
||||||
{
|
{
|
||||||
__asm
|
putrch(147);
|
||||||
{
|
|
||||||
jsr bsinit
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void textcursor(bool show)
|
void textcursor(bool show)
|
||||||
|
@ -336,6 +352,24 @@ void textcursor(bool show)
|
||||||
|
|
||||||
void gotoxy(char cx, char cy)
|
void gotoxy(char cx, char cy)
|
||||||
{
|
{
|
||||||
|
#if defined(__CBMPET__)
|
||||||
|
#define CURS_X 0xc6
|
||||||
|
#define CURS_Y 0xd8
|
||||||
|
#define SCREEN_PTR 0xc4
|
||||||
|
#define SCR_LINELEN 0xd5
|
||||||
|
|
||||||
|
__assume(cy < 25);
|
||||||
|
|
||||||
|
*(volatile char *)CURS_X = cx;
|
||||||
|
*(volatile char *)CURS_Y = cy;
|
||||||
|
|
||||||
|
if (*(volatile char *)SCR_LINELEN > 40)
|
||||||
|
cy <<= 1;
|
||||||
|
|
||||||
|
const unsigned off = cy * 40;
|
||||||
|
|
||||||
|
* (volatile unsigned *)SCREEN_PTR = off + 0x8000;
|
||||||
|
#else
|
||||||
__asm
|
__asm
|
||||||
{
|
{
|
||||||
ldx cy
|
ldx cy
|
||||||
|
@ -343,6 +377,7 @@ void gotoxy(char cx, char cy)
|
||||||
clc
|
clc
|
||||||
jsr bsplot
|
jsr bsplot
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void textcolor(char c)
|
void textcolor(char c)
|
||||||
|
@ -350,6 +385,24 @@ void textcolor(char c)
|
||||||
*(volatile char *)0x0286 = c;
|
*(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)
|
char wherex(void)
|
||||||
{
|
{
|
||||||
#if defined(__C128__) || defined(__C128B__) || defined(__C128E__)
|
#if defined(__C128__) || defined(__C128B__) || defined(__C128E__)
|
||||||
|
|
|
@ -43,6 +43,26 @@ void dispmode80col(void);
|
||||||
#define PETSCII_F7 0x88
|
#define PETSCII_F7 0x88
|
||||||
#define PETSCII_F8 0x8c
|
#define PETSCII_F8 0x8c
|
||||||
|
|
||||||
|
enum ConioColors
|
||||||
|
{
|
||||||
|
COLOR_BLACK,
|
||||||
|
COLOR_WHITE,
|
||||||
|
COLOR_RED,
|
||||||
|
COLOR_CYAN,
|
||||||
|
COLOR_PURPLE,
|
||||||
|
COLOR_GREEN,
|
||||||
|
COLOR_BLUE,
|
||||||
|
COLOR_YELLOW,
|
||||||
|
|
||||||
|
COLOR_ORANGE,
|
||||||
|
COLOR_BROWN,
|
||||||
|
COLOR_LT_RED,
|
||||||
|
COLOR_DARK_GREY,
|
||||||
|
COLOR_MED_GREY,
|
||||||
|
COLOR_LT_GREEN,
|
||||||
|
COLOR_LT_BLUE,
|
||||||
|
COLOR_LT_GREY
|
||||||
|
};
|
||||||
// Lowlevel console in/out
|
// Lowlevel console in/out
|
||||||
|
|
||||||
// using petscii translation
|
// using petscii translation
|
||||||
|
@ -74,6 +94,12 @@ void gotoxy(char x, char y);
|
||||||
|
|
||||||
inline void textcolor(char c);
|
inline void textcolor(char c);
|
||||||
|
|
||||||
|
inline void bgcolor(char c);
|
||||||
|
|
||||||
|
inline void bordercolor(char c);
|
||||||
|
|
||||||
|
inline void revers(char r);
|
||||||
|
|
||||||
inline char wherex(void);
|
inline char wherex(void);
|
||||||
|
|
||||||
inline char wherey(void);
|
inline char wherey(void);
|
||||||
|
|
|
@ -667,21 +667,19 @@ L1: rol accu
|
||||||
sbc tmp + 1
|
sbc tmp + 1
|
||||||
lda tmp + 6
|
lda tmp + 6
|
||||||
sbc tmp + 2
|
sbc tmp + 2
|
||||||
|
tax
|
||||||
lda tmp + 7
|
lda tmp + 7
|
||||||
sbc tmp + 3
|
sbc tmp + 3
|
||||||
bcc W1
|
bcc W1
|
||||||
|
stx tmp + 6
|
||||||
|
sta tmp + 7
|
||||||
lda tmp + 4
|
lda tmp + 4
|
||||||
sbc tmp + 0
|
sbc tmp + 0
|
||||||
sta tmp + 4
|
sta tmp + 4
|
||||||
lda tmp + 5
|
lda tmp + 5
|
||||||
sbc tmp + 1
|
sbc tmp + 1
|
||||||
sta tmp + 5
|
sta tmp + 5
|
||||||
lda tmp + 6
|
sec
|
||||||
sbc tmp + 2
|
|
||||||
sta tmp + 6
|
|
||||||
lda tmp + 7
|
|
||||||
sbc tmp + 3
|
|
||||||
sta tmp + 7
|
|
||||||
W1: dey
|
W1: dey
|
||||||
bne L1
|
bne L1
|
||||||
rol accu
|
rol accu
|
||||||
|
@ -758,6 +756,11 @@ __asm mul32
|
||||||
sta tmp + 6
|
sta tmp + 6
|
||||||
sta tmp + 7
|
sta tmp + 7
|
||||||
|
|
||||||
|
lda tmp + 3
|
||||||
|
ora tmp + 2
|
||||||
|
ora tmp + 1
|
||||||
|
beq WB
|
||||||
|
|
||||||
lda tmp + 0
|
lda tmp + 0
|
||||||
jsr WM
|
jsr WM
|
||||||
lda tmp + 1
|
lda tmp + 1
|
||||||
|
@ -775,6 +778,7 @@ WM:
|
||||||
stx accu + 1
|
stx accu + 1
|
||||||
sta accu
|
sta accu
|
||||||
rts
|
rts
|
||||||
|
WB: lda tmp + 0
|
||||||
W0:
|
W0:
|
||||||
sec
|
sec
|
||||||
ror
|
ror
|
||||||
|
@ -3072,7 +3076,7 @@ __asm inp_binop_sub_f32
|
||||||
|
|
||||||
#pragma bytecode(BC_BINOP_SUB_F32, inp_binop_sub_f32)
|
#pragma bytecode(BC_BINOP_SUB_F32, inp_binop_sub_f32)
|
||||||
|
|
||||||
__asm fmul8
|
__asm crt_fmul8
|
||||||
{
|
{
|
||||||
sec
|
sec
|
||||||
ror
|
ror
|
||||||
|
@ -3106,7 +3110,7 @@ W1:
|
||||||
rts
|
rts
|
||||||
}
|
}
|
||||||
|
|
||||||
__asm fmul
|
__asm crt_fmul
|
||||||
{
|
{
|
||||||
lda accu
|
lda accu
|
||||||
ora accu + 1
|
ora accu + 1
|
||||||
|
@ -3147,13 +3151,13 @@ W2:
|
||||||
beq W5
|
beq W5
|
||||||
bne W6
|
bne W6
|
||||||
W4:
|
W4:
|
||||||
jsr fmul8
|
jsr crt_fmul8
|
||||||
lda tmp + 1
|
lda tmp + 1
|
||||||
W6:
|
W6:
|
||||||
jsr fmul8
|
jsr crt_fmul8
|
||||||
W5:
|
W5:
|
||||||
lda tmp + 2
|
lda tmp + 2
|
||||||
jsr fmul8
|
jsr crt_fmul8
|
||||||
|
|
||||||
sec
|
sec
|
||||||
lda tmp + 8
|
lda tmp + 8
|
||||||
|
@ -3210,12 +3214,12 @@ __asm inp_binop_mul_f32
|
||||||
{
|
{
|
||||||
jsr freg.split_exp
|
jsr freg.split_exp
|
||||||
sty tmpy
|
sty tmpy
|
||||||
jsr fmul
|
jsr crt_fmul
|
||||||
ldy tmpy
|
ldy tmpy
|
||||||
jmp startup.exec
|
jmp startup.exec
|
||||||
}
|
}
|
||||||
|
|
||||||
__asm fdiv
|
__asm crt_fdiv
|
||||||
{
|
{
|
||||||
lda accu
|
lda accu
|
||||||
ora accu + 1
|
ora accu + 1
|
||||||
|
@ -3337,13 +3341,13 @@ ZERO:
|
||||||
__asm inp_binop_div_f32
|
__asm inp_binop_div_f32
|
||||||
{
|
{
|
||||||
jsr freg.split_exp
|
jsr freg.split_exp
|
||||||
jsr fdiv
|
jsr crt_fdiv
|
||||||
jmp startup.exec
|
jmp startup.exec
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma bytecode(BC_BINOP_DIV_F32, inp_binop_div_f32)
|
#pragma bytecode(BC_BINOP_DIV_F32, inp_binop_div_f32)
|
||||||
|
|
||||||
__asm fcmp
|
__asm crt_fcmp
|
||||||
{
|
{
|
||||||
lda accu + 3
|
lda accu + 3
|
||||||
eor tmp + 3
|
eor tmp + 3
|
||||||
|
@ -4058,9 +4062,9 @@ __asm load32
|
||||||
#pragma runtime(fmergea, freg.merge_aexp)
|
#pragma runtime(fmergea, freg.merge_aexp)
|
||||||
#pragma runtime(fadd, faddsub.fadd)
|
#pragma runtime(fadd, faddsub.fadd)
|
||||||
#pragma runtime(fsub, faddsub.fsub)
|
#pragma runtime(fsub, faddsub.fsub)
|
||||||
#pragma runtime(fmul, fmul)
|
#pragma runtime(fmul, crt_fmul)
|
||||||
#pragma runtime(fdiv, fdiv)
|
#pragma runtime(fdiv, crt_fdiv)
|
||||||
#pragma runtime(fcmp, fcmp)
|
#pragma runtime(fcmp, crt_fcmp)
|
||||||
#pragma runtime(ffromi, sint16_to_float)
|
#pragma runtime(ffromi, sint16_to_float)
|
||||||
#pragma runtime(ffromu, uint16_to_float)
|
#pragma runtime(ffromu, uint16_to_float)
|
||||||
#pragma runtime(ftoi, f32_to_i16)
|
#pragma runtime(ftoi, f32_to_i16)
|
||||||
|
@ -4558,7 +4562,7 @@ struct Heap {
|
||||||
|
|
||||||
#pragma section(heap, 0x0000, HeapStart, HeapEnd)
|
#pragma section(heap, 0x0000, HeapStart, HeapEnd)
|
||||||
|
|
||||||
__asm malloc
|
__asm crt_malloc
|
||||||
{
|
{
|
||||||
// make room for two additional bytes
|
// make room for two additional bytes
|
||||||
// to store pointer to end of used memory
|
// to store pointer to end of used memory
|
||||||
|
@ -4785,14 +4789,14 @@ hc2:
|
||||||
__asm inp_malloc
|
__asm inp_malloc
|
||||||
{
|
{
|
||||||
sty tmpy
|
sty tmpy
|
||||||
jsr malloc
|
jsr crt_malloc
|
||||||
ldy tmpy
|
ldy tmpy
|
||||||
jmp startup.exec
|
jmp startup.exec
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma bytecode(BC_MALLOC, inp_malloc)
|
#pragma bytecode(BC_MALLOC, inp_malloc)
|
||||||
|
|
||||||
__asm free
|
__asm crt_free
|
||||||
{
|
{
|
||||||
|
|
||||||
// check nullptr free
|
// check nullptr free
|
||||||
|
@ -5009,21 +5013,21 @@ nostart:
|
||||||
__asm inp_free
|
__asm inp_free
|
||||||
{
|
{
|
||||||
sty tmpy
|
sty tmpy
|
||||||
jsr free
|
jsr crt_free
|
||||||
ldy tmpy
|
ldy tmpy
|
||||||
jmp startup.exec
|
jmp startup.exec
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma bytecode(BC_FREE, inp_free)
|
#pragma bytecode(BC_FREE, inp_free)
|
||||||
|
|
||||||
__asm breakpoint
|
__asm crt_breakpoint
|
||||||
{
|
{
|
||||||
rts
|
rts
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma runtime(malloc, malloc)
|
#pragma runtime(malloc, crt_malloc)
|
||||||
#pragma runtime(free, free)
|
#pragma runtime(free, crt_free)
|
||||||
#pragma runtime(breakpoint, breakpoint)
|
#pragma runtime(breakpoint, crt_breakpoint)
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
||||||
|
|
|
@ -123,8 +123,9 @@ int lmul4f12s(int x, int y)
|
||||||
|
|
||||||
lda #0
|
lda #0
|
||||||
sta accu + 1
|
sta accu + 1
|
||||||
L2:
|
|
||||||
bcc W4
|
bcc W4
|
||||||
|
L2:
|
||||||
tay
|
tay
|
||||||
clc
|
clc
|
||||||
lda accu + 1
|
lda accu + 1
|
||||||
|
@ -165,7 +166,7 @@ W1:
|
||||||
bcc W2
|
bcc W2
|
||||||
|
|
||||||
tay
|
tay
|
||||||
sec
|
// sec ; we know it is set here
|
||||||
lda accu + 1
|
lda accu + 1
|
||||||
sbc y
|
sbc y
|
||||||
sta accu + 1
|
sta accu + 1
|
||||||
|
|
|
@ -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)
|
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;
|
char ip = 0;
|
||||||
bool delta16 = ((dx | dy) & 0xff80) != 0;
|
bool delta16 =((dx | dy) & 0xff80) != 0;
|
||||||
|
|
||||||
// ylow
|
// ylow
|
||||||
ip += asm_im(BLIT_CODE + ip, ASM_LDY, ly);
|
ip += asm_im(BLIT_CODE + ip, ASM_LDY, ly);
|
||||||
|
@ -579,33 +579,51 @@ static inline void buildline(char ly, char lx, int dx, int dy, int stride, bool
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dx && dy)
|
if (dy)
|
||||||
|
{
|
||||||
|
bool delta8 = false;
|
||||||
|
|
||||||
|
if (dx)
|
||||||
{
|
{
|
||||||
// m >= 0
|
// m >= 0
|
||||||
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP + delta16);
|
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP + delta16);
|
||||||
ip += asm_rl(BLIT_CODE + ip, ASM_BMI, delta16 ? 5 + 15 + 13 + 2 : 5 + 15 + 7 + 2);
|
char n = delta16 ? 18 + 13 + 2 : 18 + 7 + 2;
|
||||||
|
if (!up) n++;
|
||||||
|
ip += asm_rl(BLIT_CODE + ip, ASM_BMI, n);
|
||||||
|
delta8 = !delta16;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dy)
|
if (up)
|
||||||
{
|
{
|
||||||
ip += asm_np(BLIT_CODE + ip, up ? ASM_DEY : ASM_INY);
|
ip += asm_np(BLIT_CODE + ip, ASM_DEY);
|
||||||
ip += asm_im(BLIT_CODE + ip, ASM_CPY, up ? 0xff : 0x08);
|
ip += asm_rl(BLIT_CODE + ip, ASM_BPL, delta8 ? 17 : 15);
|
||||||
ip += asm_rl(BLIT_CODE + ip, ASM_BNE, 15);
|
|
||||||
|
|
||||||
ip += asm_np(BLIT_CODE + ip, ASM_CLC);
|
ip += asm_np(BLIT_CODE + ip, ASM_CLC);
|
||||||
|
ip += asm_im(BLIT_CODE + ip, ASM_LDY, 0x07);
|
||||||
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_SP);
|
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_SP);
|
||||||
ip += asm_im(BLIT_CODE + ip, ASM_ADC, stride & 0xff);
|
ip += asm_im(BLIT_CODE + ip, ASM_ADC, stride & 0xff);
|
||||||
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_SP);
|
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_SP);
|
||||||
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_SP + 1);
|
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_SP + 1);
|
||||||
ip += asm_im(BLIT_CODE + ip, ASM_ADC, stride >> 8);
|
ip += asm_im(BLIT_CODE + ip, ASM_ADC, stride >> 8);
|
||||||
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_SP + 1);
|
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_SP + 1);
|
||||||
ip += asm_im(BLIT_CODE + ip, ASM_LDY, up ? 0x07 : 0x00);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ip += asm_np(BLIT_CODE + ip, ASM_INY);
|
||||||
|
ip += asm_im(BLIT_CODE + ip, ASM_CPY, 0x08);
|
||||||
|
ip += asm_rl(BLIT_CODE + ip, ASM_BNE, delta8 ? 16 : 14);
|
||||||
|
ip += asm_im(BLIT_CODE + ip, ASM_LDY, 0x00);
|
||||||
|
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_SP);
|
||||||
|
ip += asm_im(BLIT_CODE + ip, ASM_ADC, (stride - 1) & 0xff);
|
||||||
|
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_SP);
|
||||||
|
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_SP + 1);
|
||||||
|
ip += asm_im(BLIT_CODE + ip, ASM_ADC, (stride - 1) >> 8);
|
||||||
|
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_SP + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dx && dy)
|
if (dx)
|
||||||
{
|
{
|
||||||
ip += asm_np(BLIT_CODE + ip, ASM_SEC);
|
|
||||||
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP);
|
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP);
|
||||||
|
ip += asm_np(BLIT_CODE + ip, ASM_SEC);
|
||||||
ip += asm_im(BLIT_CODE + ip, ASM_SBC, dx & 0xff);
|
ip += asm_im(BLIT_CODE + ip, ASM_SBC, dx & 0xff);
|
||||||
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_DP);
|
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_DP);
|
||||||
|
|
||||||
|
@ -614,47 +632,52 @@ static inline void buildline(char ly, char lx, int dx, int dy, int stride, bool
|
||||||
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP + 1);
|
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP + 1);
|
||||||
ip += asm_im(BLIT_CODE + ip, ASM_SBC, dx >> 8);
|
ip += asm_im(BLIT_CODE + ip, ASM_SBC, dx >> 8);
|
||||||
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_DP + 1);
|
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_DP + 1);
|
||||||
|
ip += asm_rl(BLIT_CODE + ip, ASM_BPL, 13 + 4 + 12);
|
||||||
|
|
||||||
|
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 + 13 + 13 : 4 + 13 + 7);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dx)
|
if (dx)
|
||||||
{
|
{
|
||||||
ip += asm_zp(BLIT_CODE + ip, left ? ASM_ASL : ASM_LSR, REG_D0);
|
ip += asm_zp(BLIT_CODE + ip, left ? ASM_ASL : ASM_LSR, REG_D0);
|
||||||
ip += asm_rl(BLIT_CODE + ip, ASM_BCC, 13);
|
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, 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_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);
|
|
||||||
|
|
||||||
if (left)
|
if (left)
|
||||||
{
|
{
|
||||||
|
ip += asm_im(BLIT_CODE + ip, ASM_ADC, 0xf8);
|
||||||
ip += asm_rl(BLIT_CODE + ip, ASM_BCS, 2);
|
ip += asm_rl(BLIT_CODE + ip, ASM_BCS, 2);
|
||||||
ip += asm_zp(BLIT_CODE + ip, ASM_DEC, REG_SP + 1);
|
ip += asm_zp(BLIT_CODE + ip, ASM_DEC, REG_SP + 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
ip += asm_im(BLIT_CODE + ip, ASM_ADC, 0x08);
|
||||||
ip += asm_rl(BLIT_CODE + ip, ASM_BCC, 2);
|
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_INC, REG_SP + 1);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (dx && dy)
|
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_SP);
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// l --
|
// l --
|
||||||
|
|
|
@ -110,12 +110,12 @@ float atan2(float p, float q)
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define F_EXP_0 1.0000003
|
#define F_EXP_0 1.0
|
||||||
#define F_EXP_1 0.693147059
|
#define F_EXP_1 0.69315668
|
||||||
#define F_EXP_2 0.240173099
|
#define F_EXP_2 0.240132068
|
||||||
#define F_EXP_3 0.055816392
|
#define F_EXP_3 0.055876024
|
||||||
#define F_EXP_4 0.008965036
|
#define F_EXP_4 0.008940801
|
||||||
#define F_EXP_5 0.001898429
|
#define F_EXP_5 0.001894414
|
||||||
|
|
||||||
float exp(float f)
|
float exp(float f)
|
||||||
{
|
{
|
||||||
|
@ -143,12 +143,12 @@ float exp(float f)
|
||||||
return s * x.f;
|
return s * x.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define F_LOG_0 -3.78712618
|
#define F_LOG_0 -3.78717706
|
||||||
#define F_LOG_1 10.0957081
|
#define F_LOG_1 10.0960498
|
||||||
#define F_LOG_2 -13.9747486
|
#define F_LOG_2 -13.975654
|
||||||
#define F_LOG_3 12.7568806
|
#define F_LOG_3 12.7580616
|
||||||
#define F_LOG_4 -6.48114552
|
#define F_LOG_4 -6.48190725
|
||||||
#define F_LOG_5 1.39045416
|
#define F_LOG_5 1.39064767
|
||||||
|
|
||||||
float log(float f)
|
float log(float f)
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,10 +33,15 @@ bool isfinite(float f);
|
||||||
#pragma intrinsic(sin)
|
#pragma intrinsic(sin)
|
||||||
#pragma intrinsic(cos)
|
#pragma intrinsic(cos)
|
||||||
#pragma intrinsic(tan)
|
#pragma intrinsic(tan)
|
||||||
|
#pragma intrinsic(atan)
|
||||||
|
#pragma intrinsic(atan2)
|
||||||
|
|
||||||
#pragma intrinsic(log)
|
#pragma intrinsic(log)
|
||||||
#pragma intrinsic(exp)
|
#pragma intrinsic(exp)
|
||||||
|
|
||||||
|
#pragma intrinsic(pow)
|
||||||
|
#pragma intrinsic(sqrt)
|
||||||
|
|
||||||
#pragma compile("math.c")
|
#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
|
|
@ -4,6 +4,7 @@
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <opp/utility.h>
|
#include <opp/utility.h>
|
||||||
|
#include <oscar.h>
|
||||||
|
|
||||||
namespace opp {
|
namespace opp {
|
||||||
|
|
||||||
|
@ -11,8 +12,8 @@ template <class T, int N>
|
||||||
class static_vector
|
class static_vector
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
char _space[N * sizeof(T)];
|
|
||||||
enum { m = N } _size;
|
enum { m = N } _size;
|
||||||
|
char _space[N * sizeof(T)];
|
||||||
public:
|
public:
|
||||||
typedef T element_type;
|
typedef T element_type;
|
||||||
|
|
||||||
|
@ -20,23 +21,28 @@ public:
|
||||||
|
|
||||||
static_vector(size_t n) : _size(n)
|
static_vector(size_t n) : _size(n)
|
||||||
{
|
{
|
||||||
|
#ifdef CAPACITYCHECK
|
||||||
|
if (n > N) debugcrash();
|
||||||
|
#endif
|
||||||
T * data = (T*)_space;
|
T * data = (T*)_space;
|
||||||
for(size_t i=0; i<n; i++)
|
for(size_t i=0; i<n; i++)
|
||||||
new (data + i) T;
|
new (data + i) T();
|
||||||
}
|
}
|
||||||
|
|
||||||
static_vector(const static_vector & v)
|
static_vector(const static_vector & v)
|
||||||
: _size(v._size)
|
: _size(v._size)
|
||||||
{
|
{
|
||||||
|
size_t n = _size;
|
||||||
T * data = (T*)_space, * vdata = (T*)(v._space);
|
T * data = (T*)_space, * vdata = (T*)(v._space);
|
||||||
for(size_t i=0; i<_size; i++)
|
for(size_t i=0; i<n; i++)
|
||||||
new (data + i)T(vdata[i]);
|
new (data + i)T(vdata[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
~static_vector(void)
|
~static_vector(void)
|
||||||
{
|
{
|
||||||
T * data = (T*)_space;
|
T * data = (T*)_space;
|
||||||
for(size_t i=0; i<_size; i++)
|
size_t n = _size;
|
||||||
|
for(size_t i=0; i<n; i++)
|
||||||
data[i].~T();
|
data[i].~T();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,10 +51,12 @@ public:
|
||||||
if (this != &v)
|
if (this != &v)
|
||||||
{
|
{
|
||||||
T * data = (T*)_space, * vdata = (T*)(v._space);
|
T * data = (T*)_space, * vdata = (T*)(v._space);
|
||||||
for(size_t i=0; i<_size; i++)
|
size_t n = _size;
|
||||||
|
for(size_t i=0; i<n; i++)
|
||||||
data[i].~T();
|
data[i].~T();
|
||||||
_size = v._size;
|
_size = v._size;
|
||||||
for(size_t i=0; i<_size; i++)
|
n = _size;
|
||||||
|
for(size_t i=0; i<n; i++)
|
||||||
new (data + i)T(vdata[i]);
|
new (data + i)T(vdata[i]);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -69,6 +77,11 @@ public:
|
||||||
return _size == 0;
|
return _size == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool full(void) const
|
||||||
|
{
|
||||||
|
return _size == N;
|
||||||
|
}
|
||||||
|
|
||||||
size_t capacity(void) const
|
size_t capacity(void) const
|
||||||
{
|
{
|
||||||
return N;
|
return N;
|
||||||
|
@ -76,6 +89,8 @@ public:
|
||||||
|
|
||||||
void resize(size_t n);
|
void resize(size_t n);
|
||||||
|
|
||||||
|
void clear(void);
|
||||||
|
|
||||||
T & at(size_t at)
|
T & at(size_t at)
|
||||||
{
|
{
|
||||||
return ((T*)_space)[at];
|
return ((T*)_space)[at];
|
||||||
|
@ -166,6 +181,8 @@ public:
|
||||||
((T*)_space)[_size].~T();
|
((T*)_space)[_size].~T();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void assign(size_t count, const T & t);
|
||||||
|
|
||||||
void insert(size_t at, const T & t);
|
void insert(size_t at, const T & t);
|
||||||
|
|
||||||
void erase(size_t at, size_t n = 1);
|
void erase(size_t at, size_t n = 1);
|
||||||
|
@ -177,34 +194,50 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class T, int N>
|
||||||
|
void static_vector<T, N>::clear(void)
|
||||||
|
{
|
||||||
|
T * data = (T*)_space;
|
||||||
|
for(size_t i=0; i<_size; i++)
|
||||||
|
data[i].~T();
|
||||||
|
_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
template <class T, int N>
|
template <class T, int N>
|
||||||
void static_vector<T, N>::resize(size_t n)
|
void static_vector<T, N>::resize(size_t n)
|
||||||
{
|
{
|
||||||
|
#ifdef CAPACITYCHECK
|
||||||
|
if (n > N) debugcrash();
|
||||||
|
#endif
|
||||||
T * data = (T*)_space;
|
T * data = (T*)_space;
|
||||||
if (n < _size)
|
if (n < _size)
|
||||||
{
|
{
|
||||||
for(size_t i=n; i<_size; i++)
|
for(size_t i=n; i<_size; i++)
|
||||||
data[i].~T();
|
data[i].~T();
|
||||||
_size = n;
|
|
||||||
}
|
}
|
||||||
else
|
else if (n > 0)
|
||||||
{
|
{
|
||||||
for(size_t i=_size; i<n; i++)
|
for(size_t i=_size; i<n; i++)
|
||||||
new(data + i)T;
|
new(data + i)T();
|
||||||
_size = n;
|
|
||||||
}
|
}
|
||||||
|
_size = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, int N>
|
template <class T, int N>
|
||||||
void static_vector<T, N>::push_back(const T & t)
|
void static_vector<T, N>::push_back(const T & t)
|
||||||
{
|
{
|
||||||
|
#ifdef CAPACITYCHECK
|
||||||
|
if (_size >= N) debugcrash();
|
||||||
|
#endif
|
||||||
new ((T*)_space + _size++)T(t);
|
new ((T*)_space + _size++)T(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, int N>
|
template <class T, int N>
|
||||||
void static_vector<T, N>::push_back(T && t)
|
void static_vector<T, N>::push_back(T && t)
|
||||||
{
|
{
|
||||||
|
#ifdef CAPACITYCHECK
|
||||||
|
if (_size >= N) debugcrash();
|
||||||
|
#endif
|
||||||
new ((T*)_space + _size++)T(t);
|
new ((T*)_space + _size++)T(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,14 +245,28 @@ template <class T, int N>
|
||||||
template <typename ...P>
|
template <typename ...P>
|
||||||
void static_vector<T, N>::emplace_back(const P&... p)
|
void static_vector<T, N>::emplace_back(const P&... p)
|
||||||
{
|
{
|
||||||
|
#ifdef CAPACITYCHECK
|
||||||
|
if (_size >= N) debugcrash();
|
||||||
|
#endif
|
||||||
new ((T*)_space + _size++)T(p...);
|
new ((T*)_space + _size++)T(p...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class T, int N>
|
||||||
|
void static_vector<T, N>::assign(size_t count, const T & t)
|
||||||
|
{
|
||||||
|
T * data = (T*)_space;
|
||||||
|
for(size_t i=0; i<_size; i++)
|
||||||
|
data[i].~T();
|
||||||
|
for(size_t i=0; i<count; i++)
|
||||||
|
new (data + i)T(t);
|
||||||
|
_size = count;
|
||||||
|
}
|
||||||
|
|
||||||
template <class T, int N>
|
template <class T, int N>
|
||||||
void static_vector<T, N>::insert(size_t at, const T & t)
|
void static_vector<T, N>::insert(size_t at, const T & t)
|
||||||
{
|
{
|
||||||
T * data = (T*)_space;
|
T * data = (T*)_space;
|
||||||
new (data + _size)T;
|
new (data + _size)T();
|
||||||
for(size_t i=_size; i>at; i--)
|
for(size_t i=_size; i>at; i--)
|
||||||
data[i] = move(data[i - 1]);
|
data[i] = move(data[i - 1]);
|
||||||
data[at] = t;
|
data[at] = t;
|
||||||
|
@ -240,9 +287,12 @@ void static_vector<T, N>::erase(size_t at, size_t n)
|
||||||
template <class T, int N>
|
template <class T, int N>
|
||||||
T * static_vector<T, N>::insert(T * at, const T & t)
|
T * static_vector<T, N>::insert(T * at, const T & t)
|
||||||
{
|
{
|
||||||
|
#ifdef CAPACITYCHECK
|
||||||
|
if (_size >= N) debugcrash();
|
||||||
|
#endif
|
||||||
T * data = (T*)_space;
|
T * data = (T*)_space;
|
||||||
T * dp = data + _size;
|
T * dp = data + _size;
|
||||||
new (dp)T;
|
new (dp)T();
|
||||||
while (dp != at)
|
while (dp != at)
|
||||||
{
|
{
|
||||||
dp--;
|
dp--;
|
||||||
|
|
|
@ -21,13 +21,14 @@ public:
|
||||||
vector(size_t n) : _data((T*)malloc(n * sizeof(T))), _size(n), _capacity(n)
|
vector(size_t n) : _data((T*)malloc(n * sizeof(T))), _size(n), _capacity(n)
|
||||||
{
|
{
|
||||||
for(size_t i=0; i<n; i++)
|
for(size_t i=0; i<n; i++)
|
||||||
new (_data + i) T;
|
new (_data + i) T();
|
||||||
}
|
}
|
||||||
|
|
||||||
vector(const vector & v)
|
vector(const vector & v)
|
||||||
: _data((T*)malloc(v._size * sizeof(T))), _size(v._size), _capacity(v._size)
|
: _data((T*)malloc(v._size * sizeof(T))), _size(v._size), _capacity(v._size)
|
||||||
{
|
{
|
||||||
for(size_t i=0; i<_size; i++)
|
size_t n = _size;
|
||||||
|
for(size_t i=0; i<n; i++)
|
||||||
new (_data + i)T(v._data[i]);
|
new (_data + i)T(v._data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,14 +51,16 @@ public:
|
||||||
{
|
{
|
||||||
if (this != &v)
|
if (this != &v)
|
||||||
{
|
{
|
||||||
for(size_t i=0; i<_size; i++)
|
size_t n = _size;
|
||||||
|
for(size_t i=0; i<n; i++)
|
||||||
_data[i].~T();
|
_data[i].~T();
|
||||||
free(_data);
|
free(_data);
|
||||||
|
|
||||||
_data = (T*)malloc(v._size * sizeof(T));
|
_data = (T*)malloc(v._size * sizeof(T));
|
||||||
_size = v._size;
|
_size = v._size;
|
||||||
_capacity = v._size;
|
_capacity = v._size;
|
||||||
for(size_t i=0; i<_size; i++)
|
n = _size;
|
||||||
|
for(size_t i=0; i<n; i++)
|
||||||
new (_data + i)T(v._data[i]);
|
new (_data + i)T(v._data[i]);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -94,6 +97,8 @@ public:
|
||||||
return _capacity;
|
return _capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clear(void);
|
||||||
|
|
||||||
void resize(size_t n);
|
void resize(size_t n);
|
||||||
|
|
||||||
void reserve(size_t n);
|
void reserve(size_t n);
|
||||||
|
@ -190,6 +195,8 @@ public:
|
||||||
_data[_size].~T();
|
_data[_size].~T();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void assign(size_t count, const T & t);
|
||||||
|
|
||||||
void insert(size_t at, const T & t);
|
void insert(size_t at, const T & t);
|
||||||
|
|
||||||
void erase(size_t at, size_t n = 1);
|
void erase(size_t at, size_t n = 1);
|
||||||
|
@ -204,7 +211,7 @@ protected:
|
||||||
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void vector<T>::reserve(size_t n)
|
__noinline void vector<T>::reserve(size_t n)
|
||||||
{
|
{
|
||||||
if (n > _capacity)
|
if (n > _capacity)
|
||||||
{
|
{
|
||||||
|
@ -221,7 +228,15 @@ void vector<T>::reserve(size_t n)
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void vector<T>::resize(size_t n)
|
void vector<T>::clear(void)
|
||||||
|
{
|
||||||
|
for(size_t i=0; i<_size; i++)
|
||||||
|
_data[i].~T();
|
||||||
|
_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
__noinline void vector<T>::resize(size_t n)
|
||||||
{
|
{
|
||||||
if (n < _size)
|
if (n < _size)
|
||||||
{
|
{
|
||||||
|
@ -232,7 +247,7 @@ void vector<T>::resize(size_t n)
|
||||||
else if (n < _capacity)
|
else if (n < _capacity)
|
||||||
{
|
{
|
||||||
for(size_t i=_size; i<n; i++)
|
for(size_t i=_size; i<n; i++)
|
||||||
new(_data + i)T;
|
new(_data + i)T();
|
||||||
_size = n;
|
_size = n;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -286,12 +301,27 @@ void vector<T>::emplace_back(const P&... p)
|
||||||
new (add_back())T(p...);
|
new (add_back())T(p...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void vector<T>::assign(size_t count, const T & t)
|
||||||
|
{
|
||||||
|
for(size_t i=0; i<_size; i++)
|
||||||
|
_data[i].~T();
|
||||||
|
if (count > _capacity)
|
||||||
|
{
|
||||||
|
_size = 0;
|
||||||
|
reserve(count);
|
||||||
|
}
|
||||||
|
for(size_t i=0; i<count; i++)
|
||||||
|
new (_data + i)T(t);
|
||||||
|
_size = count;
|
||||||
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void vector<T>::insert(size_t at, const T & t)
|
void vector<T>::insert(size_t at, const T & t)
|
||||||
{
|
{
|
||||||
if (_size == _capacity)
|
if (_size == _capacity)
|
||||||
reserve(_size + 1 + (_size >> 1));
|
reserve(_size + 1 + (_size >> 1));
|
||||||
new (_data + _size)T;
|
new (_data + _size)T();
|
||||||
for(size_t i=_size; i>at; i--)
|
for(size_t i=_size; i>at; i--)
|
||||||
_data[i] = move(_data[i - 1]);
|
_data[i] = move(_data[i - 1]);
|
||||||
_data[at] = t;
|
_data[at] = t;
|
||||||
|
@ -318,7 +348,7 @@ T * vector<T>::insert(T * at, const T & t)
|
||||||
at = (T *)(f + unsigned(_data));
|
at = (T *)(f + unsigned(_data));
|
||||||
}
|
}
|
||||||
T * dp = _data + _size;
|
T * dp = _data + _size;
|
||||||
new (dp)T;
|
new (dp)T();
|
||||||
while (dp != at)
|
while (dp != at)
|
||||||
{
|
{
|
||||||
dp--;
|
dp--;
|
||||||
|
|
|
@ -129,3 +129,10 @@ __native const char * oscar_expand_lzo_buf(char * dp, const char * sp)
|
||||||
|
|
||||||
return sp + 1;
|
return sp + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void debugcrash(void)
|
||||||
|
{
|
||||||
|
__asm volatile {
|
||||||
|
byt $02
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@ void breakpoint(void);
|
||||||
|
|
||||||
#pragma intrinsic(breakpoint)
|
#pragma intrinsic(breakpoint)
|
||||||
|
|
||||||
|
void debugcrash(void);
|
||||||
|
|
||||||
#pragma compile("oscar.c")
|
#pragma compile("oscar.c")
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -417,7 +417,7 @@ char * sformat(char * buff, const char * fmt, int * fps, bool print)
|
||||||
si.precision = i;
|
si.precision = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == 'd' || c == p'd')
|
if (c == 'd' || c == p'd' || c == 'i' || c == p'i')
|
||||||
{
|
{
|
||||||
bi = nformi(&si, bp, *fps++, true);
|
bi = nformi(&si, bp, *fps++, true);
|
||||||
}
|
}
|
||||||
|
@ -556,6 +556,17 @@ int sprintf(char * str, const char * fmt, ...)
|
||||||
return d - str;
|
return d - str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vprintf(const char * fmt, va_list vlist)
|
||||||
|
{
|
||||||
|
char buff[50];
|
||||||
|
sformat(buff, fmt, (int *)vlist, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
int vsprintf(char * str, const char * fmt, va_list vlist)
|
||||||
|
{
|
||||||
|
char * d = sformat(str, fmt, (int *)vlist, false);
|
||||||
|
return d - str;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool isspace(char c)
|
static inline bool isspace(char c)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
void putchar(char c);
|
void putchar(char c);
|
||||||
|
|
||||||
|
@ -18,6 +19,10 @@ void printf(const char * fmt, ...);
|
||||||
|
|
||||||
int sprintf(char * str, const char * fmt, ...);
|
int sprintf(char * str, const char * fmt, ...);
|
||||||
|
|
||||||
|
void vprintf(const char * fmt, va_list vlist);
|
||||||
|
|
||||||
|
int vsprintf(char * str, const char * fmt, va_list vlist);
|
||||||
|
|
||||||
int scanf(const char * fmt, ...);
|
int scanf(const char * fmt, ...);
|
||||||
|
|
||||||
int sscanf(const char * str, const char * fmt, ...);
|
int sscanf(const char * str, const char * fmt, ...);
|
||||||
|
|
|
@ -544,7 +544,7 @@ unsigned heapfree(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
struct Heap {
|
struct Heap {q
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
Heap * next;
|
Heap * next;
|
||||||
} * freeHeap;
|
} * freeHeap;
|
||||||
|
@ -667,6 +667,97 @@ void * calloc(int num, int size)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void * realloc(void * ptr, unsigned size)
|
||||||
|
{
|
||||||
|
if (ptr)
|
||||||
|
{
|
||||||
|
#ifdef HEAPCHECK
|
||||||
|
Heap * pheap = (Heap *)((char *)ptr - 6);
|
||||||
|
Heap * eheap = pheap->next;
|
||||||
|
|
||||||
|
unsigned psize = (char *)eheap - (char *)pheap;
|
||||||
|
|
||||||
|
void * nptr = malloc(size);
|
||||||
|
memcpy(nptr, ptr, psize - 6);
|
||||||
|
free(ptr);
|
||||||
|
return nptr;
|
||||||
|
#else
|
||||||
|
unsigned nsize = (size + 5) & ~3;
|
||||||
|
|
||||||
|
// Get heap info
|
||||||
|
Heap * pheap = (Heap *)((char *)ptr - 2);
|
||||||
|
Heap * eheap = pheap->next;
|
||||||
|
|
||||||
|
unsigned psize = (char *)eheap - (char *)pheap;
|
||||||
|
|
||||||
|
Heap * h = HeapNode.next;
|
||||||
|
Heap * hp = &HeapNode;
|
||||||
|
while (h && h < pheap)
|
||||||
|
{
|
||||||
|
hp = h;
|
||||||
|
h = h->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nsize <= psize)
|
||||||
|
{
|
||||||
|
// check if we should free some memory
|
||||||
|
if (nsize + sizeof(HeapNode) < psize)
|
||||||
|
{
|
||||||
|
Heap * nheap = (Heap *)((char *)pheap + nsize);
|
||||||
|
pheap->next = nheap;
|
||||||
|
|
||||||
|
if (h == eheap)
|
||||||
|
{
|
||||||
|
nheap->end = h->end;
|
||||||
|
nheap->next = h->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nheap->end = eheap;
|
||||||
|
nheap->next = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
hp->next = nheap;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
else if (h == eheap)
|
||||||
|
{
|
||||||
|
// Free space after this
|
||||||
|
|
||||||
|
// Check if enough space if extending
|
||||||
|
unsigned xsize = (char *)h->end - (char *)pheap;
|
||||||
|
if (xsize >= nsize)
|
||||||
|
{
|
||||||
|
if (xsize > nsize + sizeof(HeapNode))
|
||||||
|
{
|
||||||
|
Heap * nheap = (Heap *)((char *)pheap + nsize);
|
||||||
|
pheap->next = nheap;
|
||||||
|
nheap->end = h->end;
|
||||||
|
nheap->next = h->next;
|
||||||
|
hp->next = nheap;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pheap->next = h->end;
|
||||||
|
hp->next = h->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void * nptr = malloc(size);
|
||||||
|
memcpy(nptr, ptr, psize - 2);
|
||||||
|
free(ptr);
|
||||||
|
return nptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned seed = 31232;
|
static unsigned seed = 31232;
|
||||||
|
|
||||||
unsigned int rand(void)
|
unsigned int rand(void)
|
||||||
|
|
|
@ -45,6 +45,8 @@ void free(void * ptr);
|
||||||
|
|
||||||
void * calloc(int num, int size);
|
void * calloc(int num, int size);
|
||||||
|
|
||||||
|
void * realloc(void * ptr, unsigned size);
|
||||||
|
|
||||||
unsigned heapfree(void);
|
unsigned heapfree(void);
|
||||||
|
|
||||||
unsigned int rand(void);
|
unsigned int rand(void);
|
||||||
|
|
|
@ -138,6 +138,20 @@ char * cpycat(char * dst, const char * src)
|
||||||
|
|
||||||
#pragma native(cpycat)
|
#pragma native(cpycat)
|
||||||
|
|
||||||
|
char* strchr( const char* str, int ch )
|
||||||
|
{
|
||||||
|
char * p = (char *)str;
|
||||||
|
|
||||||
|
while (*p != (char)ch)
|
||||||
|
{
|
||||||
|
if (!*p)
|
||||||
|
return nullptr;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void * memset(void * dst, int value, int size)
|
void * memset(void * dst, int value, int size)
|
||||||
{
|
{
|
||||||
__asm
|
__asm
|
||||||
|
|
|
@ -21,6 +21,8 @@ int memcmp(const void * ptr1, const void * ptr2, int size);
|
||||||
|
|
||||||
void * memmove(void * dst, const void * src, int size);
|
void * memmove(void * dst, const void * src, int size);
|
||||||
|
|
||||||
|
char* strchr( const char* str, int ch );
|
||||||
|
|
||||||
#pragma intrinsic(strcpy)
|
#pragma intrinsic(strcpy)
|
||||||
|
|
||||||
#pragma intrinsic(memcpy)
|
#pragma intrinsic(memcpy)
|
||||||
|
|
|
@ -12,8 +12,8 @@ export OSCAR64_CFLAGS =
|
||||||
export OSCAR64_CXX = $(project_dir)/bin/oscar64
|
export OSCAR64_CXX = $(project_dir)/bin/oscar64
|
||||||
MKDIR_PARENT = /bin/mkdir -p -m 755
|
MKDIR_PARENT = /bin/mkdir -p -m 755
|
||||||
INSTALL = /usr/bin/install
|
INSTALL = /usr/bin/install
|
||||||
INSTALL_PROGRAM = $(INSTALL) --mode=755
|
INSTALL_PROGRAM = $(INSTALL) -m 755
|
||||||
INSTALL_DATA = $(INSTALL) --mode=644
|
INSTALL_DATA = $(INSTALL) -m 644
|
||||||
DESTDIR =
|
DESTDIR =
|
||||||
prefix = /usr/local
|
prefix = /usr/local
|
||||||
exec_prefix = $(prefix)
|
exec_prefix = $(prefix)
|
||||||
|
@ -38,7 +38,7 @@ else
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
all: --prep-build-dir compiler samples tests
|
all: compiler samples check
|
||||||
|
|
||||||
|
|
||||||
$(srcdir)/%.o: $(project_dir)/oscar64/%.cpp
|
$(srcdir)/%.o: $(project_dir)/oscar64/%.cpp
|
||||||
|
@ -56,7 +56,7 @@ $(srcdir)/%.d: $(project_dir)/oscar64/%.cpp
|
||||||
$(RM) $@.$$$$
|
$(RM) $@.$$$$
|
||||||
|
|
||||||
|
|
||||||
compiler: $(objects)
|
compiler: --prep-build-dir $(objects)
|
||||||
@$(MKDIR_PARENT) $(srcdir)
|
@$(MKDIR_PARENT) $(srcdir)
|
||||||
@echo "Linking compiler..."
|
@echo "Linking compiler..."
|
||||||
$(CXX) $(CPPFLAGS) $(objects) $(linklibs) -o $(project_dir)/bin/oscar64
|
$(CXX) $(CPPFLAGS) $(objects) $(linklibs) -o $(project_dir)/bin/oscar64
|
||||||
|
@ -85,7 +85,7 @@ samples: compiler
|
||||||
@$(MAKE) -C $(project_dir)/samples all
|
@$(MAKE) -C $(project_dir)/samples all
|
||||||
|
|
||||||
|
|
||||||
tests: compiler
|
check: compiler
|
||||||
@$(MAKE) -C $(project_dir)/autotest all
|
@$(MAKE) -C $(project_dir)/autotest all
|
||||||
|
|
||||||
install: compiler
|
install: compiler
|
||||||
|
@ -93,16 +93,16 @@ install: compiler
|
||||||
@$(MKDIR_PARENT) $(DESTDIR)$(bindir)
|
@$(MKDIR_PARENT) $(DESTDIR)$(bindir)
|
||||||
$(INSTALL_PROGRAM) $(project_dir)/bin/oscar64 $(DESTDIR)$(bindir)
|
$(INSTALL_PROGRAM) $(project_dir)/bin/oscar64 $(DESTDIR)$(bindir)
|
||||||
@$(MKDIR_PARENT) $(DESTDIR)$(includedir)/oscar64/{audio,c64,c128,cx16,gfx,nes,opp,plus4,vic20}
|
@$(MKDIR_PARENT) $(DESTDIR)$(includedir)/oscar64/{audio,c64,c128,cx16,gfx,nes,opp,plus4,vic20}
|
||||||
$(INSTALL_DATA) $(project_dir)/include/*.{h,c} $(DESTDIR)$(includedir)/oscar64
|
$(INSTALL_DATA) $(wildcard $(project_dir)/include/*.h $(project_dir)/include/*.c) $(DESTDIR)$(includedir)/oscar64
|
||||||
$(INSTALL_DATA) $(project_dir)/include/audio/*.{h,c} $(DESTDIR)$(includedir)/oscar64/audio
|
$(INSTALL_DATA) $(wildcard $(project_dir)/include/audio/*.h $(project_dir)/include/audio/*.c) $(DESTDIR)$(includedir)/oscar64/audio
|
||||||
$(INSTALL_DATA) $(project_dir)/include/c64/*.{h,c} $(DESTDIR)$(includedir)/oscar64/c64
|
$(INSTALL_DATA) $(wildcard $(project_dir)/include/c64/*.h $(project_dir)/include/c64/*.c) $(DESTDIR)$(includedir)/oscar64/c64
|
||||||
$(INSTALL_DATA) $(project_dir)/include/c128/*.{h,c} $(DESTDIR)$(includedir)/oscar64/c128
|
$(INSTALL_DATA) $(wildcard $(project_dir)/include/c128/*.h $(project_dir)/include/c128/*.c) $(DESTDIR)$(includedir)/oscar64/c128
|
||||||
$(INSTALL_DATA) $(project_dir)/include/cx16/*.{h,c} $(DESTDIR)$(includedir)/oscar64/cx16
|
$(INSTALL_DATA) $(wildcard $(project_dir)/include/cx16/*.h $(project_dir)/include/cx16/*.c) $(DESTDIR)$(includedir)/oscar64/cx16
|
||||||
$(INSTALL_DATA) $(project_dir)/include/gfx/*.{h,c} $(DESTDIR)$(includedir)/oscar64/gfx
|
$(INSTALL_DATA) $(wildcard $(project_dir)/include/gfx/*.h $(project_dir)/include/gfx/*.c) $(DESTDIR)$(includedir)/oscar64/gfx
|
||||||
$(INSTALL_DATA) $(project_dir)/include/nes/*.{h,c} $(DESTDIR)$(includedir)/oscar64/nes
|
$(INSTALL_DATA) $(wildcard $(project_dir)/include/nes/*.h $(project_dir)/include/nes/*.c) $(DESTDIR)$(includedir)/oscar64/nes
|
||||||
$(INSTALL_DATA) $(project_dir)/include/opp/*.{h,cpp} $(DESTDIR)$(includedir)/oscar64/opp
|
$(INSTALL_DATA) $(wildcard $(project_dir)/include/opp/*.h $(project_dir)/include/opp/*.cpp) $(DESTDIR)$(includedir)/oscar64/opp
|
||||||
$(INSTALL_DATA) $(project_dir)/include/plus4/*.{h,c} $(DESTDIR)$(includedir)/oscar64/plus4
|
$(INSTALL_DATA) $(wildcard $(project_dir)/include/plus4/*.h $(project_dir)/include/plus4/*.c) $(DESTDIR)$(includedir)/oscar64/plus4
|
||||||
$(INSTALL_DATA) $(project_dir)/include/vic20/*.{h,c} $(DESTDIR)$(includedir)/oscar64/vic20
|
$(INSTALL_DATA) $(wildcard $(project_dir)/include/vic20/*.h $(project_dir)/include/vic20/*.c) $(DESTDIR)$(includedir)/oscar64/vic20
|
||||||
|
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
|
|
36
oscar64.md
36
oscar64.md
|
@ -15,7 +15,7 @@ When I started this project, I was under the assumption that the 6502 would make
|
||||||
|
|
||||||
The original plan was thus to compile to an intermediate language that would be interpreted, offering the 16bit support without the added code cost. This turned out to work great from a code size perspective, but the performance was poor. So I decided to give compiling to native code a shot.
|
The original plan was thus to compile to an intermediate language that would be interpreted, offering the 16bit support without the added code cost. This turned out to work great from a code size perspective, but the performance was poor. So I decided to give compiling to native code a shot.
|
||||||
|
|
||||||
Most of the 6502 limitations can be overcome by carefull code analysis and optimizations.
|
Most of the 6502 limitations can be overcome by careful code analysis and optimizations.
|
||||||
|
|
||||||
* A second data stack relieves the CPU stack.
|
* A second data stack relieves the CPU stack.
|
||||||
* Static call graph analysis removes the need for a stack completely
|
* Static call graph analysis removes the need for a stack completely
|
||||||
|
@ -28,7 +28,7 @@ In the end, it turned out that the native code is not only significantly faster
|
||||||
|
|
||||||
## Limits and Errors
|
## Limits and Errors
|
||||||
|
|
||||||
There are still several open areas, but most targets have been reached. The current Dhrystone performance is 94 iterations per second with byte code (10993) and 405 iterations with native code (9173 Bytes). This clearly shows that Dhrystone is not a valid benchmark for optimizing compilers, because it puts the 6502 on par with a 4MHz 8088 or 68k, which it clearly is not.
|
There are still several open areas, but most targets have been reached. The current Dhrystone performance is 94 iterations per second with byte code (10993) and 442 iterations with native code (8952 Bytes). This clearly shows that Dhrystone is not a valid benchmark for optimizing compilers, because it puts the 6502 on par with a 4MHz 8088 or 68k, which it clearly is not.
|
||||||
|
|
||||||
### Language
|
### Language
|
||||||
|
|
||||||
|
@ -110,6 +110,7 @@ The compiler is command line driven, and creates an executable .prg file.
|
||||||
* -v : verbose output for diagnostics
|
* -v : verbose output for diagnostics
|
||||||
* -v2 : more verbose output
|
* -v2 : more verbose output
|
||||||
* -i : additional include paths
|
* -i : additional include paths
|
||||||
|
* -ii : set default include path
|
||||||
* -o : optional output file name
|
* -o : optional output file name
|
||||||
* -rt : alternative runtime library, replaces the crt.c (or empty for none)
|
* -rt : alternative runtime library, replaces the crt.c (or empty for none)
|
||||||
* -e : execute the result in the integrated emulator
|
* -e : execute the result in the integrated emulator
|
||||||
|
@ -128,6 +129,8 @@ The compiler is command line driven, and creates an executable .prg file.
|
||||||
* -Oa : optimize inline assembler (part of O2/O3)
|
* -Oa : optimize inline assembler (part of O2/O3)
|
||||||
* -Oz : enable auto placement of global variables in zero page (part of O3)
|
* -Oz : enable auto placement of global variables in zero page (part of O3)
|
||||||
* -Op : optimize constant parameters
|
* -Op : optimize constant parameters
|
||||||
|
* -Oo : optimize size using "outliner" (extract repeated code sequences into functions)
|
||||||
|
* -Ox : optimize pointer arithmetic by blocking shorter arrays to not cross page boundaries
|
||||||
* -g : create source level debug info and add source line numbers to asm listing
|
* -g : create source level debug info and add source line numbers to asm listing
|
||||||
* -gp : create source level debug info and add source line numbers to asm listing and static profile data
|
* -gp : create source level debug info and add source line numbers to asm listing and static profile data
|
||||||
* -tf : target format, may be prg, crt or bin
|
* -tf : target format, may be prg, crt or bin
|
||||||
|
@ -139,6 +142,7 @@ The compiler is command line driven, and creates an executable .prg file.
|
||||||
* -xz : extended zero page usage, more zero page space, but no return to basic
|
* -xz : extended zero page usage, more zero page space, but no return to basic
|
||||||
* -cid : cartridge type ID, used by vice emulator
|
* -cid : cartridge type ID, used by vice emulator
|
||||||
* -pp : compile in C++ mode
|
* -pp : compile in C++ mode
|
||||||
|
* -strict : use strict ANSI C parsing (no C++ goodies)
|
||||||
* -psci : use PETSCII encoding for all strings without prefix
|
* -psci : use PETSCII encoding for all strings without prefix
|
||||||
* -rmp : generate error files .error.map, .error.asm when linker fails
|
* -rmp : generate error files .error.map, .error.asm when linker fails
|
||||||
|
|
||||||
|
@ -173,6 +177,7 @@ A list of source files can be provided.
|
||||||
* nes_mmc3 : Nintendo entertainment system, MMC3, 512K PROM, 256K CROM
|
* nes_mmc3 : Nintendo entertainment system, MMC3, 512K PROM, 256K CROM
|
||||||
* atari : Atari 8bit systems, (0x2000..0xbc00)
|
* atari : Atari 8bit systems, (0x2000..0xbc00)
|
||||||
* x16 : Commander X16, (0x0800..0x9f00)
|
* x16 : Commander X16, (0x0800..0x9f00)
|
||||||
|
* mega65 : Mega 65, (0x2000..0xc000)
|
||||||
|
|
||||||
### C64 Cartridge formats
|
### C64 Cartridge formats
|
||||||
|
|
||||||
|
@ -332,6 +337,17 @@ The .asm file is a great resource when debugging from within e.g. the VICE monit
|
||||||
|
|
||||||
The compiler has various extensions to simplify developing for the C64.
|
The compiler has various extensions to simplify developing for the C64.
|
||||||
|
|
||||||
|
## Pragmas
|
||||||
|
|
||||||
|
Warnings can be turned on or off using the warning pragma. The scope of the pragma is currently global in most cases, so if it is turned off at some place, it is off everywhere.
|
||||||
|
|
||||||
|
#pragma warning(disable: 2000,2001)
|
||||||
|
|
||||||
|
A message can be displayed during compilation with the message pragma
|
||||||
|
|
||||||
|
#pragma message("Hello User")
|
||||||
|
|
||||||
|
|
||||||
## Embedding binary data
|
## Embedding binary data
|
||||||
|
|
||||||
The compiler supports the #embed preprocessor directive to import binary data. It converts a section of an external binary file into a sequence of numbers that can be placed into an initializer of an array.
|
The compiler supports the #embed preprocessor directive to import binary data. It converts a section of an external binary file into a sequence of numbers that can be placed into an initializer of an array.
|
||||||
|
@ -482,6 +498,8 @@ Set optimizer options that are active for the functions after it
|
||||||
* maxinline : inline any function suitable
|
* maxinline : inline any function suitable
|
||||||
* constparams : enable constant parameter folding into called functions
|
* constparams : enable constant parameter folding into called functions
|
||||||
* noconstparams : disable constant parameter folding into called functions
|
* noconstparams : disable constant parameter folding into called functions
|
||||||
|
* outline : enable outliner
|
||||||
|
* nooutline : disable outliner
|
||||||
* 0 : no optimization
|
* 0 : no optimization
|
||||||
* 1 : default optimizations
|
* 1 : default optimizations
|
||||||
* 2 : aggressive optimizations
|
* 2 : aggressive optimizations
|
||||||
|
@ -733,6 +751,11 @@ Regions can also be used to place assets such as character sets at fixed locatio
|
||||||
|
|
||||||
The #pragma data(), #pragma code() and #pragma bss() control the placement of the generated objects into sections other than the default sections.
|
The #pragma data(), #pragma code() and #pragma bss() control the placement of the generated objects into sections other than the default sections.
|
||||||
|
|
||||||
|
A global variable or function can be aligned on a given power of two start with the align pragma. This is most useful if a page crossing is problematic. The compiler may also be able to generate more efficient code, if a larger variable is page aligned.
|
||||||
|
|
||||||
|
#pragma align(myvar, 8)
|
||||||
|
#pragma align(myfunc, 256)
|
||||||
|
|
||||||
### Additional BSS sections
|
### Additional BSS sections
|
||||||
|
|
||||||
Additional bss sections can be defined on request.
|
Additional bss sections can be defined on request.
|
||||||
|
@ -740,7 +763,7 @@ Additional bss sections can be defined on request.
|
||||||
#pragma section( mybss, 0, , , bss )
|
#pragma section( mybss, 0, , , bss )
|
||||||
#pragma region( mybssregion, 0xc000, 0xd000, , , {mybss} )
|
#pragma region( mybssregion, 0xc000, 0xd000, , , {mybss} )
|
||||||
|
|
||||||
They will not be cleared on startup, so all variables placed in these segments will be unitialized. A common use for these sections is overlapping runtime variables with compressed load time assests that get expanded to their actual location during startup.
|
They will not be cleared on startup, so all variables placed in these segments will be uninitialized. A common use for these sections is overlapping runtime variables with compressed load time assests that get expanded to their actual location during startup.
|
||||||
|
|
||||||
### Heap and Stack sections
|
### Heap and Stack sections
|
||||||
|
|
||||||
|
@ -807,7 +830,7 @@ With NROM mappers, the prg and chr code is put into cartridge bank zero.
|
||||||
|
|
||||||
#pragma data(data)
|
#pragma data(data)
|
||||||
|
|
||||||
The 32KByte of prg code starts at 0x8000 and goes upto 0xff80. A startup section from 0xff80 to 0xfff9 is taken from the crt.c.
|
The 32KByte of prg code starts at 0x8000 and goes up to 0xff80. A startup section from 0xff80 to 0xfff9 is taken from the crt.c.
|
||||||
|
|
||||||
A six byte boot section is placed from 0xfffa to 0xffff in all modes, which has to be populated by the game code with the appropriate pointers.
|
A six byte boot section is placed from 0xfffa to 0xffff in all modes, which has to be populated by the game code with the appropriate pointers.
|
||||||
|
|
||||||
|
@ -931,6 +954,11 @@ The compiler provides two levels of interrupt safe functions. The specifier __i
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
### Assembler optimizer
|
||||||
|
|
||||||
|
The compiler uses various optimizations on inline assembler that may not have the expected result in all cases. The optimizer can be disabled for a range of code with e.g. #pragma optimize(noasm) or for an individual __asm statement by using __asm volatile {}.
|
||||||
|
The assembler optimizer is enabled with optimization levels O2 and up.
|
||||||
|
|
||||||
# Helping the compiler optimizing
|
# Helping the compiler optimizing
|
||||||
|
|
||||||
The compiler does various optimization when compiling the code, but there are some rules to follow, things to avoid and hints to place to help the compiler to generate optimal code.
|
The compiler does various optimization when compiling the code, but there are some rules to follow, things to avoid and hints to place to help the compiler to generate optimal code.
|
||||||
|
|
16
oscar64.sln
16
oscar64.sln
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 16
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 16.0.31624.102
|
VisualStudioVersion = 17.13.35931.197
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "oscar64", "oscar64\oscar64.vcxproj", "{1DBC623E-6109-41FE-B1BB-9B43FC984F7D}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "oscar64", "oscar64\oscar64.vcxproj", "{1DBC623E-6109-41FE-B1BB-9B43FC984F7D}"
|
||||||
EndProject
|
EndProject
|
||||||
|
@ -23,10 +23,14 @@ Global
|
||||||
{1DBC623E-6109-41FE-B1BB-9B43FC984F7D}.Release|x64.Build.0 = Release|x64
|
{1DBC623E-6109-41FE-B1BB-9B43FC984F7D}.Release|x64.Build.0 = Release|x64
|
||||||
{1DBC623E-6109-41FE-B1BB-9B43FC984F7D}.Release|x86.ActiveCfg = Release|Win32
|
{1DBC623E-6109-41FE-B1BB-9B43FC984F7D}.Release|x86.ActiveCfg = Release|Win32
|
||||||
{1DBC623E-6109-41FE-B1BB-9B43FC984F7D}.Release|x86.Build.0 = Release|Win32
|
{1DBC623E-6109-41FE-B1BB-9B43FC984F7D}.Release|x86.Build.0 = Release|Win32
|
||||||
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Debug|x64.ActiveCfg = Debug
|
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Debug|x86.ActiveCfg = Debug
|
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Debug|x64.Build.0 = Debug|x64
|
||||||
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Release|x64.ActiveCfg = Release
|
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Release|x86.ActiveCfg = Release
|
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Debug|x86.Build.0 = Debug|x86
|
||||||
|
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Release|x64.Build.0 = Release|x64
|
||||||
|
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Release|x86.ActiveCfg = Release|x86
|
||||||
|
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Release|x86.Build.0 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
@ -421,11 +421,13 @@ protected:
|
||||||
array = a2;
|
array = a2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = size; i < to; i++) array[i] = T{};
|
||||||
|
|
||||||
size = to;
|
size = to;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
void Parition(const F & f, int l, int r)
|
void Partition(const F & f, int l, int r)
|
||||||
{
|
{
|
||||||
if (r > l + 1)
|
if (r > l + 1)
|
||||||
{
|
{
|
||||||
|
@ -442,8 +444,8 @@ protected:
|
||||||
}
|
}
|
||||||
array[pi] = p;
|
array[pi] = p;
|
||||||
|
|
||||||
Parition(f, l, pi);
|
Partition(f, l, pi);
|
||||||
Parition(f, pi + 1, r);
|
Partition(f, pi + 1, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
|
@ -618,10 +620,22 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Fill(const T& t)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
array[i] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
array[i] = T{};
|
||||||
|
}
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
void Sort(const F & f)
|
void Sort(const F & f)
|
||||||
{
|
{
|
||||||
Parition(f, 0, size);
|
Partition(f, 0, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
__forceinline T& operator[](int n)
|
__forceinline T& operator[](int n)
|
||||||
|
|
|
@ -293,7 +293,7 @@ const char* AsmInstructionNames[NUM_ASM_INS_TYPES] = {
|
||||||
"INV", "BYT"
|
"INV", "BYT"
|
||||||
};
|
};
|
||||||
|
|
||||||
int AsmInsModeSize[NUM_ASM_INS_MODES] = {
|
int AsmInsModeSize[NUM_ASM_INS_MODES_X] = {
|
||||||
1,
|
1,
|
||||||
2,
|
2,
|
||||||
2,
|
2,
|
||||||
|
@ -306,6 +306,8 @@ int AsmInsModeSize[NUM_ASM_INS_MODES] = {
|
||||||
2,
|
2,
|
||||||
2,
|
2,
|
||||||
2,
|
2,
|
||||||
|
0,
|
||||||
|
2
|
||||||
};
|
};
|
||||||
|
|
||||||
void InitAssembler(void)
|
void InitAssembler(void)
|
||||||
|
|
|
@ -31,7 +31,9 @@ enum AsmInsMode
|
||||||
|
|
||||||
NUM_ASM_INS_MODES,
|
NUM_ASM_INS_MODES,
|
||||||
|
|
||||||
ASMIM_IMMEDIATE_ADDRESS
|
ASMIM_IMMEDIATE_ADDRESS,
|
||||||
|
|
||||||
|
NUM_ASM_INS_MODES_X,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AsmInsData
|
struct AsmInsData
|
||||||
|
@ -45,6 +47,8 @@ extern AsmInsData DecInsData[256];
|
||||||
|
|
||||||
extern short AsmInsOpcodes[NUM_ASM_INS_TYPES][NUM_ASM_INS_MODES];
|
extern short AsmInsOpcodes[NUM_ASM_INS_TYPES][NUM_ASM_INS_MODES];
|
||||||
|
|
||||||
|
extern int AsmInsModeSize[NUM_ASM_INS_MODES_X];
|
||||||
|
|
||||||
extern const char* AsmInstructionNames[NUM_ASM_INS_TYPES];
|
extern const char* AsmInstructionNames[NUM_ASM_INS_TYPES];
|
||||||
|
|
||||||
AsmInsType FindAsmInstruction(const char * ins);
|
AsmInsType FindAsmInstruction(const char * ins);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
class BitVector
|
class BitVector
|
||||||
{
|
{
|
||||||
|
|
|
@ -3461,11 +3461,14 @@ ByteCode ByteCodeBasicBlock::RelationalOperator(InterCodeProcedure* proc, const
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (ins->mSrc[1].mTemp < 0)
|
if (ins->mSrc[1].mTemp < 0)
|
||||||
|
{
|
||||||
|
if (ins->mSrc[1].mType == IT_INT16 || ins->mSrc[1].mMemory == IM_ABSOLUTE)
|
||||||
{
|
{
|
||||||
ByteCodeInstruction lins(BC_LOAD_REG_16);
|
ByteCodeInstruction lins(BC_LOAD_REG_16);
|
||||||
lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
|
lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
|
||||||
lins.mRegisterFinal = ins->mSrc[0].mFinal;
|
lins.mRegisterFinal = ins->mSrc[0].mFinal;
|
||||||
mIns.Push(lins);
|
mIns.Push(lins);
|
||||||
|
|
||||||
if (csigned)
|
if (csigned)
|
||||||
{
|
{
|
||||||
ByteCodeInstruction cins(BC_BINOP_CMPSI_16);
|
ByteCodeInstruction cins(BC_BINOP_CMPSI_16);
|
||||||
|
@ -3479,7 +3482,36 @@ ByteCode ByteCodeBasicBlock::RelationalOperator(InterCodeProcedure* proc, const
|
||||||
mIns.Push(cins);
|
mIns.Push(cins);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ByteCodeInstruction bins(BC_LEA_ABS);
|
||||||
|
bins.mRegister = BC_REG_ACCU;
|
||||||
|
bins.mLinkerObject = ins->mSrc[1].mLinkerObject;
|
||||||
|
bins.mValue = int(ins->mSrc[1].mIntConst);
|
||||||
|
bins.mRelocate = true;
|
||||||
|
mIns.Push(bins);
|
||||||
|
|
||||||
|
if (csigned)
|
||||||
|
{
|
||||||
|
ByteCodeInstruction cins(BC_BINOP_CMPSR_16);
|
||||||
|
cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
|
||||||
|
cins.mRegisterFinal = ins->mSrc[0].mFinal;
|
||||||
|
mIns.Push(cins);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ByteCodeInstruction cins(BC_BINOP_CMPUR_16);
|
||||||
|
cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
|
||||||
|
cins.mRegisterFinal = ins->mSrc[0].mFinal;
|
||||||
|
mIns.Push(cins);
|
||||||
|
}
|
||||||
|
|
||||||
|
code = TransposeBranchCondition(code);
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (ins->mSrc[0].mTemp < 0)
|
else if (ins->mSrc[0].mTemp < 0)
|
||||||
|
{
|
||||||
|
if (ins->mSrc[0].mType == IT_INT16 || ins->mSrc[0].mMemory == IM_ABSOLUTE)
|
||||||
{
|
{
|
||||||
ByteCodeInstruction lins(BC_LOAD_REG_16);
|
ByteCodeInstruction lins(BC_LOAD_REG_16);
|
||||||
lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
|
lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
|
||||||
|
@ -3552,6 +3584,31 @@ ByteCode ByteCodeBasicBlock::RelationalOperator(InterCodeProcedure* proc, const
|
||||||
code = TransposeBranchCondition(code);
|
code = TransposeBranchCondition(code);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
ByteCodeInstruction bins(BC_LEA_ABS);
|
||||||
|
bins.mRegister = BC_REG_ACCU;
|
||||||
|
bins.mLinkerObject = ins->mSrc[0].mLinkerObject;
|
||||||
|
bins.mValue = int(ins->mSrc[0].mIntConst);
|
||||||
|
bins.mRelocate = true;
|
||||||
|
mIns.Push(bins);
|
||||||
|
|
||||||
|
if (csigned)
|
||||||
|
{
|
||||||
|
ByteCodeInstruction cins(BC_BINOP_CMPSR_16);
|
||||||
|
cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
|
||||||
|
cins.mRegisterFinal = ins->mSrc[1].mFinal;
|
||||||
|
mIns.Push(cins);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ByteCodeInstruction cins(BC_BINOP_CMPUR_16);
|
||||||
|
cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
|
||||||
|
cins.mRegisterFinal = ins->mSrc[1].mFinal;
|
||||||
|
mIns.Push(cins);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
ByteCodeInstruction lins(BC_LOAD_REG_16);
|
ByteCodeInstruction lins(BC_LOAD_REG_16);
|
||||||
lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
|
lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
|
||||||
|
|
|
@ -174,13 +174,13 @@ void Compiler::RegisterRuntime(const Location & loc, const Ident* ident)
|
||||||
if (bcdec->mType == DT_CONST_ASSEMBLER)
|
if (bcdec->mType == DT_CONST_ASSEMBLER)
|
||||||
{
|
{
|
||||||
if (!bcdec->mLinkerObject)
|
if (!bcdec->mLinkerObject)
|
||||||
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mValue, nullptr);
|
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec, nullptr);
|
||||||
linkerObject = bcdec->mLinkerObject;
|
linkerObject = bcdec->mLinkerObject;
|
||||||
}
|
}
|
||||||
else if (bcdec->mType == DT_LABEL)
|
else if (bcdec->mType == DT_LABEL)
|
||||||
{
|
{
|
||||||
if (!bcdec->mBase->mLinkerObject)
|
if (!bcdec->mBase->mLinkerObject)
|
||||||
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase->mValue, nullptr);
|
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase, nullptr);
|
||||||
|
|
||||||
linkerObject = bcdec->mBase->mLinkerObject;
|
linkerObject = bcdec->mBase->mLinkerObject;
|
||||||
offset = int(bcdec->mInteger);
|
offset = int(bcdec->mInteger);
|
||||||
|
@ -466,7 +466,7 @@ void Compiler::CompileProcedure(InterCodeProcedure* proc)
|
||||||
printf("Generate native code <%s>\n", proc->mIdent->mString);
|
printf("Generate native code <%s>\n", proc->mIdent->mString);
|
||||||
|
|
||||||
ncproc->Compile(proc);
|
ncproc->Compile(proc);
|
||||||
mNativeProcedures.Push(ncproc);
|
mNativeCodeGenerator->mProcedures.Push(ncproc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -508,6 +508,8 @@ bool Compiler::GenerateCode(void)
|
||||||
regionZeroPage = mLinker->AddRegion(identZeroPage, 0x00e0, 0x00ff);
|
regionZeroPage = mLinker->AddRegion(identZeroPage, 0x00e0, 0x00ff);
|
||||||
else if (mCompilerOptions & (COPT_EXTENDED_ZERO_PAGE | COPT_TARGET_NES))
|
else if (mCompilerOptions & (COPT_EXTENDED_ZERO_PAGE | COPT_TARGET_NES))
|
||||||
regionZeroPage = mLinker->AddRegion(identZeroPage, 0x0080, 0x00ff);
|
regionZeroPage = mLinker->AddRegion(identZeroPage, 0x0080, 0x00ff);
|
||||||
|
else if (mTargetMachine == TMACH_PET_8K || mTargetMachine == TMACH_PET_16K || mTargetMachine == TMACH_PET_32K)
|
||||||
|
regionZeroPage = mLinker->AddRegion(identZeroPage, 0x00ed, 0x00f7);
|
||||||
else
|
else
|
||||||
regionZeroPage = mLinker->AddRegion(identZeroPage, 0x00f7, 0x00ff);
|
regionZeroPage = mLinker->AddRegion(identZeroPage, 0x00f7, 0x00ff);
|
||||||
}
|
}
|
||||||
|
@ -521,6 +523,12 @@ bool Compiler::GenerateCode(void)
|
||||||
{
|
{
|
||||||
switch (mTargetMachine)
|
switch (mTargetMachine)
|
||||||
{
|
{
|
||||||
|
case TMACH_MEGA65:
|
||||||
|
if (mCompilerOptions & COPT_NATIVE)
|
||||||
|
regionStartup = mLinker->AddRegion(identStartup, 0x2001, 0x2080);
|
||||||
|
else
|
||||||
|
regionStartup = mLinker->AddRegion(identStartup, 0x2001, 0x2100);
|
||||||
|
break;
|
||||||
case TMACH_C64:
|
case TMACH_C64:
|
||||||
case TMACH_X16:
|
case TMACH_X16:
|
||||||
if (mCompilerOptions & COPT_NATIVE)
|
if (mCompilerOptions & COPT_NATIVE)
|
||||||
|
@ -623,6 +631,9 @@ bool Compiler::GenerateCode(void)
|
||||||
{
|
{
|
||||||
switch (mTargetMachine)
|
switch (mTargetMachine)
|
||||||
{
|
{
|
||||||
|
case TMACH_MEGA65:
|
||||||
|
regionBytecode = mLinker->AddRegion(identBytecode, 0x2100, 0x2200);
|
||||||
|
break;
|
||||||
case TMACH_C64:
|
case TMACH_C64:
|
||||||
case TMACH_X16:
|
case TMACH_X16:
|
||||||
regionBytecode = mLinker->AddRegion(identBytecode, 0x0900, 0x0a00);
|
regionBytecode = mLinker->AddRegion(identBytecode, 0x0900, 0x0a00);
|
||||||
|
@ -684,6 +695,9 @@ bool Compiler::GenerateCode(void)
|
||||||
{
|
{
|
||||||
switch (mTargetMachine)
|
switch (mTargetMachine)
|
||||||
{
|
{
|
||||||
|
case TMACH_MEGA65:
|
||||||
|
regionMain = mLinker->AddRegion(identMain, 0x2300, 0xc000);
|
||||||
|
break;
|
||||||
case TMACH_C64:
|
case TMACH_C64:
|
||||||
regionMain = mLinker->AddRegion(identMain, 0x0a00, 0xa000);
|
regionMain = mLinker->AddRegion(identMain, 0x0a00, 0xa000);
|
||||||
break;
|
break;
|
||||||
|
@ -735,6 +749,14 @@ bool Compiler::GenerateCode(void)
|
||||||
{
|
{
|
||||||
switch (mTargetMachine)
|
switch (mTargetMachine)
|
||||||
{
|
{
|
||||||
|
case TMACH_MEGA65:
|
||||||
|
// TODO: Disable M65 cartridges for now.
|
||||||
|
//
|
||||||
|
// if (mCompilerOptions & (COPT_TARGET_CRT8 | COPT_TARGET_CRT16))
|
||||||
|
// regionMain = mLinker->AddRegion(identMain, 0x2666, 0xff00);
|
||||||
|
// else
|
||||||
|
regionMain = mLinker->AddRegion(identMain, 0x2080, 0xc000);
|
||||||
|
break;
|
||||||
case TMACH_C64:
|
case TMACH_C64:
|
||||||
|
|
||||||
if (mCompilerOptions & (COPT_TARGET_CRT8 | COPT_TARGET_CRT16))
|
if (mCompilerOptions & (COPT_TARGET_CRT8 | COPT_TARGET_CRT16))
|
||||||
|
@ -910,7 +932,7 @@ bool Compiler::GenerateCode(void)
|
||||||
if (mCompilerOptions & COPT_VERBOSE)
|
if (mCompilerOptions & COPT_VERBOSE)
|
||||||
printf("Generate intermediate code\n");
|
printf("Generate intermediate code\n");
|
||||||
|
|
||||||
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, dcrtstart->mValue, nullptr);
|
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, dcrtstart, nullptr);
|
||||||
for (int i = 0; i < mCompilationUnits->mReferenced.Size(); i++)
|
for (int i = 0; i < mCompilationUnits->mReferenced.Size(); i++)
|
||||||
{
|
{
|
||||||
Declaration* dec = mCompilationUnits->mReferenced[i];
|
Declaration* dec = mCompilationUnits->mReferenced[i];
|
||||||
|
@ -993,7 +1015,7 @@ bool Compiler::GenerateCode(void)
|
||||||
if (bcdec->mType == DT_CONST_ASSEMBLER)
|
if (bcdec->mType == DT_CONST_ASSEMBLER)
|
||||||
{
|
{
|
||||||
if (!bcdec->mLinkerObject)
|
if (!bcdec->mLinkerObject)
|
||||||
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mValue, nullptr);
|
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec, nullptr);
|
||||||
mByteCodeGenerator->mExtByteCodes[i] = bcdec->mLinkerObject;
|
mByteCodeGenerator->mExtByteCodes[i] = bcdec->mLinkerObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1036,13 +1058,18 @@ bool Compiler::GenerateCode(void)
|
||||||
mCompilationUnits->mSectionStack->mSections.Push(proc->mLinkerObject->mStackSection);
|
mCompilationUnits->mSectionStack->mSections.Push(proc->mLinkerObject->mStackSection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mNativeCodeGenerator->OutlineFunctions();
|
||||||
|
|
||||||
mNativeCodeGenerator->BuildFunctionProxies();
|
mNativeCodeGenerator->BuildFunctionProxies();
|
||||||
|
|
||||||
for (int i = 0; i < mNativeProcedures.Size(); i++)
|
for (int i = 0; i < mNativeCodeGenerator->mProcedures.Size(); i++)
|
||||||
{
|
{
|
||||||
if (mCompilerOptions & COPT_VERBOSE2)
|
if (mCompilerOptions & COPT_VERBOSE2)
|
||||||
printf("Assemble native code <%s>\n", mNativeProcedures[i]->mInterProc->mIdent->mString);
|
{
|
||||||
mNativeProcedures[i]->Assemble();
|
if (mNativeCodeGenerator->mProcedures[i]->mInterProc)
|
||||||
|
printf("Assemble native code <%s>\n", mNativeCodeGenerator->mProcedures[i]->mInterProc->mIdent->mString);
|
||||||
|
}
|
||||||
|
mNativeCodeGenerator->mProcedures[i]->Assemble();
|
||||||
}
|
}
|
||||||
|
|
||||||
LinkerObject* byteCodeObject = nullptr;
|
LinkerObject* byteCodeObject = nullptr;
|
||||||
|
@ -1068,13 +1095,13 @@ bool Compiler::GenerateCode(void)
|
||||||
if (bcdec->mType == DT_CONST_ASSEMBLER)
|
if (bcdec->mType == DT_CONST_ASSEMBLER)
|
||||||
{
|
{
|
||||||
if (!bcdec->mLinkerObject)
|
if (!bcdec->mLinkerObject)
|
||||||
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mValue, nullptr);
|
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec, nullptr);
|
||||||
linkerObject = bcdec->mLinkerObject;
|
linkerObject = bcdec->mLinkerObject;
|
||||||
}
|
}
|
||||||
else if (bcdec->mType == DT_LABEL)
|
else if (bcdec->mType == DT_LABEL)
|
||||||
{
|
{
|
||||||
if (!bcdec->mBase->mLinkerObject)
|
if (!bcdec->mBase->mLinkerObject)
|
||||||
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase->mValue, nullptr);
|
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase, nullptr);
|
||||||
linkerObject = bcdec->mBase->mLinkerObject;
|
linkerObject = bcdec->mBase->mLinkerObject;
|
||||||
offset = int(bcdec->mInteger);
|
offset = int(bcdec->mInteger);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ public:
|
||||||
GlobalOptimizer* mGlobalOptimizer;
|
GlobalOptimizer* mGlobalOptimizer;
|
||||||
|
|
||||||
GrowingArray<ByteCodeProcedure*> mByteCodeFunctions;
|
GrowingArray<ByteCodeProcedure*> mByteCodeFunctions;
|
||||||
ExpandingArray<NativeCodeProcedure*> mNativeProcedures;
|
|
||||||
|
|
||||||
TargetMachine mTargetMachine;
|
TargetMachine mTargetMachine;
|
||||||
uint64 mCompilerOptions;
|
uint64 mCompilerOptions;
|
||||||
|
|
|
@ -14,6 +14,8 @@ static const uint64 COPT_OPTIMIZE_AUTO_ZEROPAGE = 1ULL << 8;
|
||||||
static const uint64 COPT_OPTIMIZE_CONST_PARAMS = 1ULL << 9;
|
static const uint64 COPT_OPTIMIZE_CONST_PARAMS = 1ULL << 9;
|
||||||
static const uint64 COPT_OPTIMIZE_MERGE_CALLS = 1ULL << 10;
|
static const uint64 COPT_OPTIMIZE_MERGE_CALLS = 1ULL << 10;
|
||||||
static const uint64 COPT_OPTIMIZE_GLOBAL = 1ULL << 11;
|
static const uint64 COPT_OPTIMIZE_GLOBAL = 1ULL << 11;
|
||||||
|
static const uint64 COPT_OPTIMIZE_OUTLINE = 1ULL << 12;
|
||||||
|
static const uint64 COPT_OPTIMIZE_PAGE_CROSSING = 1ULL << 13;
|
||||||
|
|
||||||
static const uint64 COPT_OPTIMIZE_CODE_SIZE = 1ULL << 16;
|
static const uint64 COPT_OPTIMIZE_CODE_SIZE = 1ULL << 16;
|
||||||
static const uint64 COPT_NATIVE = 1ULL << 17;
|
static const uint64 COPT_NATIVE = 1ULL << 17;
|
||||||
|
@ -42,6 +44,7 @@ static const uint64 COPT_PETSCII = 1ULL << 53;
|
||||||
static const uint64 COPT_ERROR_FILES = 1ULL << 54;
|
static const uint64 COPT_ERROR_FILES = 1ULL << 54;
|
||||||
|
|
||||||
static const uint64 COPT_PROFILEINFO = 1ULL << 55;
|
static const uint64 COPT_PROFILEINFO = 1ULL << 55;
|
||||||
|
static const uint64 COPT_STRICT = 1ULL << 56;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,7 +52,7 @@ static const uint64 COPT_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE |
|
||||||
|
|
||||||
static const uint64 COPT_OPTIMIZE_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS;
|
static const uint64 COPT_OPTIMIZE_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS;
|
||||||
|
|
||||||
static const uint64 COPT_OPTIMIZE_SIZE = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_CODE_SIZE | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS | COPT_OPTIMIZE_GLOBAL;
|
static const uint64 COPT_OPTIMIZE_SIZE = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_CODE_SIZE | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS | COPT_OPTIMIZE_GLOBAL;// | COPT_OPTIMIZE_OUTLINE;
|
||||||
|
|
||||||
static const uint64 COPT_OPTIMIZE_SPEED = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS | COPT_OPTIMIZE_GLOBAL;
|
static const uint64 COPT_OPTIMIZE_SPEED = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS | COPT_OPTIMIZE_GLOBAL;
|
||||||
|
|
||||||
|
@ -76,7 +79,8 @@ enum TargetMachine
|
||||||
TMACH_NES_MMC1,
|
TMACH_NES_MMC1,
|
||||||
TMACH_NES_MMC3,
|
TMACH_NES_MMC3,
|
||||||
TMACH_ATARI,
|
TMACH_ATARI,
|
||||||
TMACH_X16
|
TMACH_X16,
|
||||||
|
TMACH_MEGA65
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ int CompressLZO(uint8* dst, const uint8* source, int size)
|
||||||
while (pi < 127 && pos < size)
|
while (pi < 127 && pos < size)
|
||||||
{
|
{
|
||||||
int bi = pi, bj = 0;
|
int bi = pi, bj = 0;
|
||||||
for (int i = 1; i < (pos < 255 ? pos : 255); i++)
|
for (int i = 1; i <= (pos < 255 ? pos : 255); i++)
|
||||||
{
|
{
|
||||||
int j = 0;
|
int j = 0;
|
||||||
while (j < 127 && pos + j < size && source[pos - i + j] == source[pos + j])
|
while (j < 127 && pos + j < size && source[pos - i + j] == source[pos + j])
|
||||||
|
|
|
@ -651,6 +651,7 @@ Expression* ConstexprInterpreter::EvalConstructor(Expression* exp)
|
||||||
{
|
{
|
||||||
mProcType = exp->mLeft->mDecType;
|
mProcType = exp->mLeft->mDecType;
|
||||||
|
|
||||||
|
Expression* pex = exp->mRight;
|
||||||
Declaration* cdec = exp->mLeft->mDecType->mParams;
|
Declaration* cdec = exp->mLeft->mDecType->mParams;
|
||||||
|
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
|
@ -659,6 +660,28 @@ Expression* ConstexprInterpreter::EvalConstructor(Expression* exp)
|
||||||
mParams[pos].PutPtr(Value(&mResult));
|
mParams[pos].PutPtr(Value(&mResult));
|
||||||
pos = 2;
|
pos = 2;
|
||||||
|
|
||||||
|
if (pex->mType == EX_LIST)
|
||||||
|
pex = pex->mRight;
|
||||||
|
else
|
||||||
|
pex = nullptr;
|
||||||
|
cdec = cdec->mNext;
|
||||||
|
|
||||||
|
while (pex && pex->mType == EX_LIST)
|
||||||
|
{
|
||||||
|
if (!AddParam(pos, pex->mLeft, cdec))
|
||||||
|
return exp;
|
||||||
|
|
||||||
|
pex = pex->mRight;
|
||||||
|
if (cdec)
|
||||||
|
cdec = cdec->mNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pex)
|
||||||
|
{
|
||||||
|
if (!AddParam(pos, pex, cdec))
|
||||||
|
return exp;
|
||||||
|
}
|
||||||
|
|
||||||
mHeap = new ExpandingArray<Value*>();
|
mHeap = new ExpandingArray<Value*>();
|
||||||
|
|
||||||
Execute(exp->mLeft->mDecValue->mValue);
|
Execute(exp->mLeft->mDecValue->mValue);
|
||||||
|
@ -754,6 +777,9 @@ bool ConstexprInterpreter::AddParam(int& pos, Expression* pex, Declaration* dec)
|
||||||
|
|
||||||
Expression* ConstexprInterpreter::EvalCall(Expression* exp)
|
Expression* ConstexprInterpreter::EvalCall(Expression* exp)
|
||||||
{
|
{
|
||||||
|
if (!exp->mLeft->mDecValue || !exp->mLeft->mDecValue->mValue)
|
||||||
|
return exp;
|
||||||
|
|
||||||
mProcType = exp->mLeft->mDecType;
|
mProcType = exp->mLeft->mDecType;
|
||||||
|
|
||||||
Expression* pex = exp->mRight;
|
Expression* pex = exp->mRight;
|
||||||
|
@ -1020,6 +1046,9 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalUnary(Expression* exp, con
|
||||||
break;
|
break;
|
||||||
case TK_MUL:
|
case TK_MUL:
|
||||||
return vl.GetPtr();
|
return vl.GetPtr();
|
||||||
|
case TK_SIZEOF:
|
||||||
|
v.PutInt(vl.mDecType->mSize);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible operator", TokenNames[exp->mToken]);
|
mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible operator", TokenNames[exp->mToken]);
|
||||||
}
|
}
|
||||||
|
@ -1168,6 +1197,26 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalCall(Expression* exp, Cons
|
||||||
mResult = Value(exp->mLocation, TheFloatTypeDeclaration);
|
mResult = Value(exp->mLocation, TheFloatTypeDeclaration);
|
||||||
mResult.PutFloat(::exp(mParams[0].GetFloat()));
|
mResult.PutFloat(::exp(mParams[0].GetFloat()));
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(iname->mString, "sqrt"))
|
||||||
|
{
|
||||||
|
mResult = Value(exp->mLocation, TheFloatTypeDeclaration);
|
||||||
|
mResult.PutFloat(::sqrt(mParams[0].GetFloat()));
|
||||||
|
}
|
||||||
|
else if (!strcmp(iname->mString, "atan"))
|
||||||
|
{
|
||||||
|
mResult = Value(exp->mLocation, TheFloatTypeDeclaration);
|
||||||
|
mResult.PutFloat(::atan(mParams[0].GetFloat()));
|
||||||
|
}
|
||||||
|
else if (!strcmp(iname->mString, "atan2"))
|
||||||
|
{
|
||||||
|
mResult = Value(exp->mLocation, TheFloatTypeDeclaration);
|
||||||
|
mResult.PutFloat(::atan2(mParams[0].GetFloat(), mParams[1].GetFloat()));
|
||||||
|
}
|
||||||
|
else if (!strcmp(iname->mString, "pow"))
|
||||||
|
{
|
||||||
|
mResult = Value(exp->mLocation, TheFloatTypeDeclaration);
|
||||||
|
mResult.PutFloat(::pow(mParams[0].GetFloat(), mParams[1].GetFloat()));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
mErrors->Error(exp->mLeft->mDecValue->mLocation, EERR_OBJECT_NOT_FOUND, "Unknown intrinsic function", iname);
|
mErrors->Error(exp->mLeft->mDecValue->mLocation, EERR_OBJECT_NOT_FOUND, "Unknown intrinsic function", iname);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,17 @@ DeclarationScope::~DeclarationScope(void)
|
||||||
delete[] mHash;
|
delete[] mHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeclarationScope* DeclarationScope::Clone(void) const
|
||||||
|
{
|
||||||
|
DeclarationScope* scope = new DeclarationScope(mParent, mLevel, mName);
|
||||||
|
for (int i = 0; i < mHashSize; i++)
|
||||||
|
{
|
||||||
|
if (mHash[i].mIdent)
|
||||||
|
scope->Insert(mHash[i].mIdent, mHash[i].mDec);
|
||||||
|
}
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
|
||||||
const Ident* DeclarationScope::Mangle(const Ident* ident) const
|
const Ident* DeclarationScope::Mangle(const Ident* ident) const
|
||||||
{
|
{
|
||||||
if (mName && ident)
|
if (mName && ident)
|
||||||
|
@ -145,7 +156,7 @@ void DeclarationScope::End(const Location& loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression::Expression(const Location& loc, ExpressionType type)
|
Expression::Expression(const Location& loc, ExpressionType type)
|
||||||
: mLocation(loc), mEndLocation(loc), mType(type), mLeft(nullptr), mRight(nullptr), mConst(false), mDecType(nullptr), mDecValue(nullptr), mToken(TK_NONE)
|
: mLocation(loc), mEndLocation(loc), mType(type), mLeft(nullptr), mRight(nullptr), mConst(false), mDecType(nullptr), mDecValue(nullptr), mToken(TK_NONE), mFlags(0)
|
||||||
{
|
{
|
||||||
static uint32 gUID = 0;
|
static uint32 gUID = 0;
|
||||||
mUID = gUID++;
|
mUID = gUID++;
|
||||||
|
@ -263,6 +274,9 @@ void Expression::Dump(int ident) const
|
||||||
case EX_FOR:
|
case EX_FOR:
|
||||||
printf("FOR");
|
printf("FOR");
|
||||||
break;
|
break;
|
||||||
|
case EX_FORBODY:
|
||||||
|
printf("FORBODY");
|
||||||
|
break;
|
||||||
case EX_DO:
|
case EX_DO:
|
||||||
printf("DO");
|
printf("DO");
|
||||||
break;
|
break;
|
||||||
|
@ -335,6 +349,9 @@ void Expression::Dump(int ident) const
|
||||||
case EX_LABEL:
|
case EX_LABEL:
|
||||||
printf("LABEL %s", mDecValue->mIdent->mString);
|
printf("LABEL %s", mDecValue->mIdent->mString);
|
||||||
break;
|
break;
|
||||||
|
case EX_AGGREGATE:
|
||||||
|
printf("AGGREGATE");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
|
@ -488,6 +505,63 @@ Expression* Expression::LogicInvertExpression(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Expression::ReplaceVariable(Declaration* pvar, Declaration* nvar)
|
||||||
|
{
|
||||||
|
if (mLeft) mLeft->ReplaceVariable(pvar, nvar);
|
||||||
|
if (mRight) mRight->ReplaceVariable(pvar, nvar);
|
||||||
|
|
||||||
|
if (mType == EX_VARIABLE && mDecValue == pvar)
|
||||||
|
mDecValue = nvar;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression* Expression::ToAlternateThis(Declaration* pthis, Declaration* nthis)
|
||||||
|
{
|
||||||
|
Expression* left = mLeft ? mLeft->ToAlternateThis(pthis, nthis) : nullptr;
|
||||||
|
Expression* right = mRight ? mRight->ToAlternateThis(pthis, nthis) : nullptr;
|
||||||
|
Declaration* decType = mDecType, * decValue = mDecValue;
|
||||||
|
|
||||||
|
Declaration* lp = pthis, * np = nthis;
|
||||||
|
while (lp)
|
||||||
|
{
|
||||||
|
if (decType == lp->mBase)
|
||||||
|
decType = np->mBase;
|
||||||
|
else if (decType == lp->mBase->mBase)
|
||||||
|
decType = np->mBase->mBase;
|
||||||
|
if (decValue == lp)
|
||||||
|
decValue = np;
|
||||||
|
|
||||||
|
lp = lp->mNext;
|
||||||
|
np = np->mNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mType == EX_QUALIFY && mLeft->mDecType != left->mDecType)
|
||||||
|
{
|
||||||
|
Declaration* pe = mLeft->mDecType->mParams, * ne = left->mDecType->mParams;
|
||||||
|
while (pe && ne && pe != mDecValue)
|
||||||
|
{
|
||||||
|
pe = pe->mNext;
|
||||||
|
ne = ne->mNext;
|
||||||
|
}
|
||||||
|
decValue = ne;
|
||||||
|
decType = ne->mBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left == mLeft && right == mRight && decType == mDecType && decValue == mDecValue)
|
||||||
|
return this;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Expression* nexp = new Expression(mLocation, mType);
|
||||||
|
nexp->mLeft = left;
|
||||||
|
nexp->mRight = right;
|
||||||
|
nexp->mDecType = decType;
|
||||||
|
nexp->mDecValue = decValue;
|
||||||
|
nexp->mToken = mToken;
|
||||||
|
nexp->mConst = mConst;
|
||||||
|
|
||||||
|
return nexp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Expression* Expression::ConstantDereference(Errors* errors, LinkerSection* dataSection)
|
Expression* Expression::ConstantDereference(Errors* errors, LinkerSection* dataSection)
|
||||||
{
|
{
|
||||||
if (mType == EX_VARIABLE)
|
if (mType == EX_VARIABLE)
|
||||||
|
@ -605,6 +679,19 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
else if (mType == EX_PREFIX && mToken == TK_SIZEOF)
|
||||||
|
{
|
||||||
|
if (mLeft->mDecType->mFlags & DTF_DEFINED)
|
||||||
|
{
|
||||||
|
Expression* ex = new Expression(mLocation, EX_CONSTANT);
|
||||||
|
Declaration* dec = new Declaration(mLocation, DT_CONST_INTEGER);
|
||||||
|
dec->mBase = TheSignedIntTypeDeclaration;
|
||||||
|
dec->mInteger = mLeft->mDecType->mSize;
|
||||||
|
ex->mDecValue = dec;
|
||||||
|
ex->mDecType = dec->mBase;
|
||||||
|
return ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (mType == EX_PREFIX && mLeft->mType == EX_CONSTANT)
|
else if (mType == EX_PREFIX && mLeft->mType == EX_CONSTANT)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -688,14 +775,29 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
|
||||||
ex->mDecType = mDecType;
|
ex->mDecType = mDecType;
|
||||||
return ex;
|
return ex;
|
||||||
}
|
}
|
||||||
else if (mType == EX_PREFIX && mToken == TK_BINARY_AND && mLeft->mType == EX_INDEX && mLeft->mLeft->mType == EX_VARIABLE && (mLeft->mLeft->mDecValue->mFlags & (DTF_STATIC | DTF_GLOBAL)) && mLeft->mRight->mType == EX_CONSTANT)
|
else if (mType == EX_PREFIX && mToken == TK_BINARY_AND && mLeft->mType == EX_INDEX &&
|
||||||
|
mLeft->mLeft->mType == EX_VARIABLE && mLeft->mLeft->mDecType->mType == DT_TYPE_ARRAY &&
|
||||||
|
(mLeft->mLeft->mDecValue->mFlags & (DTF_STATIC | DTF_GLOBAL)) && mLeft->mRight->mType == EX_CONSTANT)
|
||||||
{
|
{
|
||||||
|
Declaration* vdec = mLeft->mLeft->mDecValue;
|
||||||
|
|
||||||
Expression* ex = new Expression(mLocation, EX_VARIABLE);
|
Expression* ex = new Expression(mLocation, EX_VARIABLE);
|
||||||
Declaration* dec = new Declaration(mLocation, DT_VARIABLE_REF);
|
Declaration* dec = new Declaration(mLocation, DT_VARIABLE_REF);
|
||||||
dec->mFlags = mLeft->mLeft->mDecValue->mFlags;
|
|
||||||
dec->mBase = mLeft->mLeft->mDecValue;
|
if (vdec->mType == DT_VARIABLE_REF)
|
||||||
|
{
|
||||||
|
dec->mFlags = vdec->mFlags;
|
||||||
|
dec->mBase = vdec->mBase;
|
||||||
|
dec->mSize = mLeft->mLeft->mDecType->mBase->mSize - int(mLeft->mRight->mDecValue->mInteger) * dec->mSize;
|
||||||
|
dec->mOffset = int(mLeft->mRight->mDecValue->mInteger) * dec->mSize + vdec->mOffset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dec->mFlags = vdec->mFlags;
|
||||||
|
dec->mBase = vdec;
|
||||||
dec->mSize = mLeft->mLeft->mDecType->mBase->mSize - int(mLeft->mRight->mDecValue->mInteger) * dec->mSize;
|
dec->mSize = mLeft->mLeft->mDecType->mBase->mSize - int(mLeft->mRight->mDecValue->mInteger) * dec->mSize;
|
||||||
dec->mOffset = int(mLeft->mRight->mDecValue->mInteger) * dec->mSize;
|
dec->mOffset = int(mLeft->mRight->mDecValue->mInteger) * dec->mSize;
|
||||||
|
}
|
||||||
ex->mDecValue = dec;
|
ex->mDecValue = dec;
|
||||||
ex->mDecType = mLeft->mLeft->mDecType;
|
ex->mDecType = mLeft->mLeft->mDecType;
|
||||||
return ex;
|
return ex;
|
||||||
|
@ -819,11 +921,19 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
|
||||||
{
|
{
|
||||||
int64 ival = 0, ileft = mLeft->mDecValue->mInteger, iright = mRight->mDecValue->mInteger;
|
int64 ival = 0, ileft = mLeft->mDecValue->mInteger, iright = mRight->mDecValue->mInteger;
|
||||||
|
|
||||||
bool signop =
|
Declaration* dtype = TheSignedIntTypeDeclaration;
|
||||||
(mLeft->mDecValue->mBase->mSize < 2 || (mLeft->mDecValue->mBase->mFlags & DTF_SIGNED)) &&
|
if (mLeft->mDecValue->mBase->mSize > mRight->mDecValue->mBase->mSize)
|
||||||
(mRight->mDecValue->mBase->mSize < 2 || (mRight->mDecValue->mBase->mFlags & DTF_SIGNED));
|
dtype = mLeft->mDecValue->mBase;
|
||||||
|
else if (mLeft->mDecValue->mBase->mSize < mRight->mDecValue->mBase->mSize)
|
||||||
|
dtype = mRight->mDecValue->mBase;
|
||||||
|
else if (mLeft->mDecValue->mBase->mSize > 1)
|
||||||
|
{
|
||||||
|
if ((mLeft->mDecValue->mBase->mFlags & DTF_SIGNED) && !(mRight->mDecValue->mBase->mFlags & DTF_SIGNED))
|
||||||
|
dtype = mRight->mDecValue->mBase;
|
||||||
|
else
|
||||||
|
dtype = mLeft->mDecValue->mBase;
|
||||||
|
}
|
||||||
|
|
||||||
bool promote = true;
|
|
||||||
switch (mToken)
|
switch (mToken)
|
||||||
{
|
{
|
||||||
case TK_ADD:
|
case TK_ADD:
|
||||||
|
@ -837,27 +947,25 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
|
||||||
break;
|
break;
|
||||||
case TK_DIV:
|
case TK_DIV:
|
||||||
if (iright == 0)
|
if (iright == 0)
|
||||||
errors->Error(mLocation, EERR_INVALID_VALUE, "Constant division by zero");
|
return this;
|
||||||
else if (signop)
|
else if (dtype->mFlags & DTF_SIGNED)
|
||||||
ival = ileft / iright;
|
ival = ileft / iright;
|
||||||
else
|
else
|
||||||
ival = (uint64)ileft / (uint64)iright;
|
ival = (uint64)ileft / (uint64)iright;
|
||||||
break;
|
break;
|
||||||
case TK_MOD:
|
case TK_MOD:
|
||||||
if (iright == 0)
|
if (iright == 0)
|
||||||
errors->Error(mLocation, EERR_INVALID_VALUE, "Constant division by zero");
|
return this;
|
||||||
else if (signop)
|
else if (dtype->mFlags & DTF_SIGNED)
|
||||||
ival = ileft % iright;
|
ival = ileft % iright;
|
||||||
else
|
else
|
||||||
ival = (uint64)ileft % (uint64)iright;
|
ival = (uint64)ileft % (uint64)iright;
|
||||||
break;
|
break;
|
||||||
case TK_LEFT_SHIFT:
|
case TK_LEFT_SHIFT:
|
||||||
ival = ileft << iright;
|
ival = ileft << iright;
|
||||||
promote = false;
|
|
||||||
break;
|
break;
|
||||||
case TK_RIGHT_SHIFT:
|
case TK_RIGHT_SHIFT:
|
||||||
ival = ileft >> iright;
|
ival = ileft >> iright;
|
||||||
promote = false;
|
|
||||||
break;
|
break;
|
||||||
case TK_BINARY_AND:
|
case TK_BINARY_AND:
|
||||||
ival = ileft & iright;
|
ival = ileft & iright;
|
||||||
|
@ -874,29 +982,14 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
|
||||||
|
|
||||||
Expression* ex = new Expression(mLocation, EX_CONSTANT);
|
Expression* ex = new Expression(mLocation, EX_CONSTANT);
|
||||||
Declaration* dec = new Declaration(mLocation, DT_CONST_INTEGER);
|
Declaration* dec = new Declaration(mLocation, DT_CONST_INTEGER);
|
||||||
if (promote)
|
dec->mBase = dtype;
|
||||||
{
|
dec->mInteger = signextend(ival, dec->mBase);
|
||||||
if (mLeft->mDecValue->mBase->mSize <= 2 && mRight->mDecValue->mBase->mSize <= 2)
|
|
||||||
dec->mBase = ival < 32768 ? TheSignedIntTypeDeclaration : TheUnsignedIntTypeDeclaration;
|
|
||||||
else
|
|
||||||
dec->mBase = ival < 2147483648 ? TheSignedLongTypeDeclaration : TheUnsignedLongTypeDeclaration;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (mLeft->mDecValue->mBase->mSize < 2)
|
|
||||||
dec->mBase = TheSignedIntTypeDeclaration;
|
|
||||||
else
|
|
||||||
dec->mBase = mLeft->mDecValue->mBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
dec->mInteger = ival;
|
|
||||||
ex->mDecValue = dec;
|
ex->mDecValue = dec;
|
||||||
ex->mDecType = dec->mBase;
|
ex->mDecType = dec->mBase;
|
||||||
return ex;
|
return ex;
|
||||||
}
|
}
|
||||||
else if ((mLeft->mDecValue->mType == DT_CONST_INTEGER || mLeft->mDecValue->mType == DT_CONST_FLOAT) && (mRight->mDecValue->mType == DT_CONST_INTEGER || mRight->mDecValue->mType == DT_CONST_FLOAT))
|
else if ((mLeft->mDecValue->mType == DT_CONST_INTEGER || mLeft->mDecValue->mType == DT_CONST_FLOAT) && (mRight->mDecValue->mType == DT_CONST_INTEGER || mRight->mDecValue->mType == DT_CONST_FLOAT))
|
||||||
{
|
{
|
||||||
|
|
||||||
double dval;
|
double dval;
|
||||||
double dleft = mLeft->mDecValue->mType == DT_CONST_INTEGER ? mLeft->mDecValue->mInteger : mLeft->mDecValue->mNumber;
|
double dleft = mLeft->mDecValue->mType == DT_CONST_INTEGER ? mLeft->mDecValue->mInteger : mLeft->mDecValue->mNumber;
|
||||||
double dright = mRight->mDecValue->mType == DT_CONST_INTEGER ? mRight->mDecValue->mInteger : mRight->mDecValue->mNumber;
|
double dright = mRight->mDecValue->mType == DT_CONST_INTEGER ? mRight->mDecValue->mInteger : mRight->mDecValue->mNumber;
|
||||||
|
@ -951,6 +1044,20 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
|
||||||
ex->mDecType = dec->mBase;
|
ex->mDecType = dec->mBase;
|
||||||
return ex;
|
return ex;
|
||||||
}
|
}
|
||||||
|
else if (mLeft->mDecValue->mType == DT_CONST_ADDRESS && mRight->mDecValue->mType == DT_CONST_ADDRESS && mToken == TK_SUB)
|
||||||
|
{
|
||||||
|
if (mLeft->mDecType->mType == DT_TYPE_POINTER && mRight->mDecType->mType == DT_TYPE_POINTER &&
|
||||||
|
mLeft->mDecType->mBase->IsConstSame(mRight->mDecType->mBase))
|
||||||
|
{
|
||||||
|
Expression* ex = new Expression(mLocation, EX_CONSTANT);
|
||||||
|
Declaration* dec = new Declaration(mLocation, DT_CONST_INTEGER);
|
||||||
|
dec->mBase = TheSignedIntTypeDeclaration;
|
||||||
|
dec->mInteger = (mLeft->mDecValue->mInteger - mRight->mDecValue->mInteger) / mLeft->mDecType->mBase->mSize;
|
||||||
|
ex->mDecValue = dec;
|
||||||
|
ex->mDecType = dec->mBase;
|
||||||
|
return ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
#if 0
|
#if 0
|
||||||
else if (mLeft->mDecValue->mType == DT_CONST_POINTER && mRight->mDecValue->mType == DT_CONST_INTEGER && (mToken == TK_ADD || mToken == TK_SUB))
|
else if (mLeft->mDecValue->mType == DT_CONST_POINTER && mRight->mDecValue->mType == DT_CONST_INTEGER && (mToken == TK_ADD || mToken == TK_SUB))
|
||||||
{
|
{
|
||||||
|
@ -1031,6 +1138,26 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (mType == EX_LOGICAL_AND && mLeft->mType == EX_CONSTANT)
|
||||||
|
{
|
||||||
|
if (mLeft->mDecValue->mType == DT_CONST_INTEGER)
|
||||||
|
{
|
||||||
|
if (mLeft->mDecValue->mInteger == 0)
|
||||||
|
return mLeft;
|
||||||
|
else
|
||||||
|
return mRight->ConstantFold(errors, dataSection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mType == EX_LOGICAL_OR && mLeft->mType == EX_CONSTANT)
|
||||||
|
{
|
||||||
|
if (mLeft->mDecValue->mType == DT_CONST_INTEGER)
|
||||||
|
{
|
||||||
|
if (mLeft->mDecValue->mInteger != 0)
|
||||||
|
return mLeft;
|
||||||
|
else
|
||||||
|
return mRight->ConstantFold(errors, dataSection);
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (mType == EX_CONDITIONAL && mLeft->mType == EX_CONSTANT)
|
else if (mType == EX_CONDITIONAL && mLeft->mType == EX_CONSTANT)
|
||||||
{
|
{
|
||||||
if (mLeft->mDecValue->mType == DT_CONST_INTEGER)
|
if (mLeft->mDecValue->mType == DT_CONST_INTEGER)
|
||||||
|
@ -1066,7 +1193,7 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
|
||||||
return ex;
|
return ex;
|
||||||
}
|
}
|
||||||
else if (mType == EX_BINARY && mToken == TK_ADD && mLeft->mType == EX_VARIABLE && mLeft->mDecValue->mType == DT_VARIABLE && (mLeft->mDecValue->mFlags & DTF_CONST) &&
|
else if (mType == EX_BINARY && mToken == TK_ADD && mLeft->mType == EX_VARIABLE && mLeft->mDecValue->mType == DT_VARIABLE && (mLeft->mDecValue->mFlags & DTF_CONST) &&
|
||||||
mLeft->mDecValue && mRight->mDecValue && mLeft->mDecValue->mValue->mType == EX_CONSTANT &&
|
mLeft->mDecValue && mRight->mDecValue && mLeft->mDecValue->mValue && mLeft->mDecValue->mValue->mType == EX_CONSTANT &&
|
||||||
mLeft->mDecType->mType == DT_TYPE_POINTER && mRight->mType == EX_CONSTANT && mRight->mDecValue->mType == DT_CONST_INTEGER)
|
mLeft->mDecType->mType == DT_TYPE_POINTER && mRight->mType == EX_CONSTANT && mRight->mDecValue->mType == DT_CONST_INTEGER)
|
||||||
{
|
{
|
||||||
mLeft = mLeft->mDecValue->mValue;
|
mLeft = mLeft->mDecValue->mValue;
|
||||||
|
@ -1132,6 +1259,10 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
|
||||||
ex->mDecType = mDecType;
|
ex->mDecType = mDecType;
|
||||||
return ex;
|
return ex;
|
||||||
}
|
}
|
||||||
|
else if (mType == EX_VARIABLE && mDecType->IsSimpleType() && (mDecValue->mFlags & DTF_CONST) && mDecValue->mValue && mDecValue->mValue->mType == EX_INITIALIZATION && mDecValue->mValue->mRight->mType == EX_CONSTANT)
|
||||||
|
{
|
||||||
|
return mDecValue->mValue->mRight;
|
||||||
|
}
|
||||||
else if (mType == EX_CALL && mLeft->mType == EX_CONSTANT && (mLeft->mDecValue->mFlags & DTF_INTRINSIC) && mRight && mRight->mType == EX_CONSTANT)
|
else if (mType == EX_CALL && mLeft->mType == EX_CONSTANT && (mLeft->mDecValue->mFlags & DTF_INTRINSIC) && mRight && mRight->mType == EX_CONSTANT)
|
||||||
{
|
{
|
||||||
Declaration* decf = mLeft->mDecValue, * decp = mRight->mDecValue;
|
Declaration* decf = mLeft->mDecValue, * decp = mRight->mDecValue;
|
||||||
|
@ -1140,6 +1271,7 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
|
||||||
if (decp->mType == DT_CONST_FLOAT || decp->mType == DT_CONST_INTEGER)
|
if (decp->mType == DT_CONST_FLOAT || decp->mType == DT_CONST_INTEGER)
|
||||||
{
|
{
|
||||||
double d = decp->mType == DT_CONST_FLOAT ? decp->mNumber : decp->mInteger;
|
double d = decp->mType == DT_CONST_FLOAT ? decp->mNumber : decp->mInteger;
|
||||||
|
double e = 0.0;
|
||||||
|
|
||||||
bool check = false;
|
bool check = false;
|
||||||
|
|
||||||
|
@ -1159,6 +1291,10 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
|
||||||
d = log(d);
|
d = log(d);
|
||||||
else if (!strcmp(iname->mString, "exp"))
|
else if (!strcmp(iname->mString, "exp"))
|
||||||
d = exp(d);
|
d = exp(d);
|
||||||
|
else if (!strcmp(iname->mString, "sqrt"))
|
||||||
|
d = sqrt(d);
|
||||||
|
else if (!strcmp(iname->mString, "atan"))
|
||||||
|
d = atan(d);
|
||||||
else
|
else
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
|
@ -1171,6 +1307,36 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
|
||||||
return ex;
|
return ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (mType == EX_CALL && mLeft->mType == EX_CONSTANT && (mLeft->mDecValue->mFlags & DTF_INTRINSIC) && mRight &&
|
||||||
|
mRight->mType == EX_LIST && mRight->mLeft->mType == EX_CONSTANT && mRight->mRight->mType == EX_CONSTANT)
|
||||||
|
{
|
||||||
|
Declaration* decf = mLeft->mDecValue, * decp1 = mRight->mLeft->mDecValue, * decp2 = mRight->mRight->mDecValue;
|
||||||
|
const Ident* iname = decf->mQualIdent;
|
||||||
|
|
||||||
|
if ((decp1->mType == DT_CONST_FLOAT || decp1->mType == DT_CONST_INTEGER) &&
|
||||||
|
(decp2->mType == DT_CONST_FLOAT || decp2->mType == DT_CONST_INTEGER))
|
||||||
|
{
|
||||||
|
double d1 = decp1->mType == DT_CONST_FLOAT ? decp1->mNumber : decp1->mInteger;
|
||||||
|
double d2 = decp2->mType == DT_CONST_FLOAT ? decp2->mNumber : decp2->mInteger;
|
||||||
|
|
||||||
|
bool check = false;
|
||||||
|
|
||||||
|
if (!strcmp(iname->mString, "pow"))
|
||||||
|
d1 = pow(d1, d2);
|
||||||
|
else if (!strcmp(iname->mString, "atan2"))
|
||||||
|
d1 = atan2(d1, d2);
|
||||||
|
else
|
||||||
|
return this;
|
||||||
|
|
||||||
|
Expression* ex = new Expression(mLocation, EX_CONSTANT);
|
||||||
|
Declaration* dec = new Declaration(mLocation, DT_CONST_FLOAT);
|
||||||
|
dec->mBase = TheFloatTypeDeclaration;
|
||||||
|
dec->mNumber = d1;
|
||||||
|
ex->mDecValue = dec;
|
||||||
|
ex->mDecType = dec->mBase;
|
||||||
|
return ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (mType == EX_CALL && mLeft->mType == EX_CONSTANT && (mLeft->mDecValue->mFlags & DTF_CONSTEXPR) && dataSection)
|
else if (mType == EX_CALL && mLeft->mType == EX_CONSTANT && (mLeft->mDecValue->mFlags & DTF_CONSTEXPR) && dataSection)
|
||||||
{
|
{
|
||||||
ConstexprInterpreter cinter(mLocation, errors, dataSection);
|
ConstexprInterpreter cinter(mLocation, errors, dataSection);
|
||||||
|
@ -1195,6 +1361,7 @@ Declaration::Declaration(const Location& loc, DecType type)
|
||||||
mConst(nullptr), mMutable(nullptr), mVolatile(nullptr),
|
mConst(nullptr), mMutable(nullptr), mVolatile(nullptr),
|
||||||
mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr), mMoveConstructor(nullptr), mMoveAssignment(nullptr),
|
mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr), mMoveConstructor(nullptr), mMoveAssignment(nullptr),
|
||||||
mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(nullptr),
|
mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(nullptr),
|
||||||
|
mVectorMoveConstructor(nullptr), mVectorMoveAssignment(nullptr),
|
||||||
mVTable(nullptr), mTemplate(nullptr), mForwardParam(nullptr), mForwardCall(nullptr),
|
mVTable(nullptr), mTemplate(nullptr), mForwardParam(nullptr), mForwardCall(nullptr),
|
||||||
mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mFriends(nullptr),
|
mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mFriends(nullptr),
|
||||||
mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1),
|
mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1),
|
||||||
|
@ -1216,7 +1383,7 @@ int Declaration::Stride(void) const
|
||||||
{
|
{
|
||||||
if (mStride > 0)
|
if (mStride > 0)
|
||||||
return mStride;
|
return mStride;
|
||||||
else if (mBase)
|
else if (mBase && mBase->mType != DT_TYPE_VOID)
|
||||||
return mBase->mSize;
|
return mBase->mSize;
|
||||||
else
|
else
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1319,6 +1486,51 @@ Declaration* Declaration::ConstCast(Declaration* ntype)
|
||||||
pdec->mSize = 2;
|
pdec->mSize = 2;
|
||||||
return pdec;
|
return pdec;
|
||||||
}
|
}
|
||||||
|
else if (mType == DT_VARIABLE && mBase->mType == DT_TYPE_ARRAY)
|
||||||
|
{
|
||||||
|
Expression* ex = new Expression(mLocation, EX_VARIABLE);
|
||||||
|
ex->mDecType = mBase;
|
||||||
|
ex->mDecValue = this;
|
||||||
|
|
||||||
|
Declaration* pdec = this->Clone();
|
||||||
|
pdec->mType = DT_CONST_POINTER;
|
||||||
|
pdec->mValue = ex;
|
||||||
|
pdec->mBase = ntype;
|
||||||
|
pdec->mSize = 2;
|
||||||
|
|
||||||
|
return pdec;
|
||||||
|
}
|
||||||
|
else if (mType == DT_VARIABLE_REF)
|
||||||
|
{
|
||||||
|
Declaration* vtype = mBase->mBase;
|
||||||
|
while (vtype && vtype->mType == DT_TYPE_STRUCT)
|
||||||
|
{
|
||||||
|
Declaration* dec = vtype->mParams;
|
||||||
|
while (dec && dec->mOffset != mOffset)
|
||||||
|
dec = dec->mNext;
|
||||||
|
if (dec)
|
||||||
|
vtype = dec->mBase;
|
||||||
|
else
|
||||||
|
vtype = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vtype && vtype->mType == DT_TYPE_ARRAY)
|
||||||
|
{
|
||||||
|
Expression* ex = new Expression(mLocation, EX_VARIABLE);
|
||||||
|
ex->mDecType = mBase->mBase;
|
||||||
|
ex->mDecValue = this;
|
||||||
|
|
||||||
|
Declaration* pdec = this->Clone();
|
||||||
|
pdec->mType = DT_CONST_POINTER;
|
||||||
|
pdec->mValue = ex;
|
||||||
|
pdec->mBase = ntype;
|
||||||
|
pdec->mSize = 2;
|
||||||
|
|
||||||
|
return pdec;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return this;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -1464,7 +1676,9 @@ const Ident* Declaration::FullIdent(void)
|
||||||
Declaration* dec = mBase->mParams;
|
Declaration* dec = mBase->mParams;
|
||||||
while (dec)
|
while (dec)
|
||||||
{
|
{
|
||||||
tident = tident->Mangle(dec->mBase->MangleIdent()->mString);
|
const Ident* mident = dec->mBase->MangleIdent();
|
||||||
|
if (mident)
|
||||||
|
tident = tident->Mangle(mident->mString);
|
||||||
dec = dec->mNext;
|
dec = dec->mNext;
|
||||||
if (dec)
|
if (dec)
|
||||||
tident = tident->Mangle(",");
|
tident = tident->Mangle(",");
|
||||||
|
@ -1600,26 +1814,31 @@ const Ident* Declaration::MangleIdent(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
dec = dec->mNext;
|
dec = dec->mNext;
|
||||||
if (dec)
|
if (mMangleIdent && dec)
|
||||||
mMangleIdent = mMangleIdent->Mangle(",");
|
mMangleIdent = mMangleIdent->Mangle(",");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mMangleIdent = Ident::Unique("void");
|
mMangleIdent = Ident::Unique("void");
|
||||||
}
|
}
|
||||||
else
|
else if (mQualIdent)
|
||||||
mMangleIdent = mQualIdent;
|
mMangleIdent = mQualIdent;
|
||||||
|
else
|
||||||
|
mMangleIdent = mIdent;
|
||||||
|
|
||||||
if (mTemplate)
|
if (mTemplate)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mMangleIdent)
|
||||||
|
{
|
||||||
if (mFlags & DTF_CONST)
|
if (mFlags & DTF_CONST)
|
||||||
mMangleIdent = mMangleIdent->PreMangle("const ");
|
mMangleIdent = mMangleIdent->PreMangle("const ");
|
||||||
if (mFlags & DTF_VOLATILE)
|
if (mFlags & DTF_VOLATILE)
|
||||||
mMangleIdent = mMangleIdent->PreMangle("volatile ");
|
mMangleIdent = mMangleIdent->PreMangle("volatile ");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return mMangleIdent;
|
return mMangleIdent;
|
||||||
}
|
}
|
||||||
|
@ -1679,19 +1898,8 @@ Declaration* Declaration::ExpandTemplate(DeclarationScope* scope)
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Declaration::ResolveTemplate(Expression* pexp, Declaration* tdec)
|
bool Declaration::ResolveTemplateParameterList(Expression* pexp, Declaration* pdec, bool preliminary)
|
||||||
{
|
{
|
||||||
Declaration* pdec = tdec->mBase->mParams;
|
|
||||||
|
|
||||||
// Insert partially resolved templates
|
|
||||||
Declaration* ptdec = tdec->mTemplate->mParams;
|
|
||||||
while (ptdec)
|
|
||||||
{
|
|
||||||
if (ptdec->mBase)
|
|
||||||
mScope->Insert(ptdec->mIdent, ptdec->mBase);
|
|
||||||
ptdec = ptdec->mNext;
|
|
||||||
}
|
|
||||||
|
|
||||||
Declaration* phead = nullptr, * ptail = nullptr;
|
Declaration* phead = nullptr, * ptail = nullptr;
|
||||||
int pcnt = 0;
|
int pcnt = 0;
|
||||||
|
|
||||||
|
@ -1727,7 +1935,7 @@ bool Declaration::ResolveTemplate(Expression* pexp, Declaration* tdec)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!ResolveTemplate(ex->mDecType, pdec->mBase))
|
if (!ResolveTemplate(ex->mDecType, pdec->mBase, false, preliminary))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
pdec = pdec->mNext;
|
pdec = pdec->mNext;
|
||||||
|
@ -1741,6 +1949,9 @@ bool Declaration::ResolveTemplate(Expression* pexp, Declaration* tdec)
|
||||||
{
|
{
|
||||||
if (pdec->mType == DT_PACK_ARGUMENT)
|
if (pdec->mType == DT_PACK_ARGUMENT)
|
||||||
{
|
{
|
||||||
|
if (preliminary)
|
||||||
|
return true;
|
||||||
|
|
||||||
Declaration* tpdec = new Declaration(pdec->mLocation, DT_PACK_TYPE);
|
Declaration* tpdec = new Declaration(pdec->mLocation, DT_PACK_TYPE);
|
||||||
if (pdec->mBase->mType == DT_TYPE_REFERENCE)
|
if (pdec->mBase->mType == DT_TYPE_REFERENCE)
|
||||||
tpdec->mIdent = pdec->mBase->mBase->mIdent;
|
tpdec->mIdent = pdec->mBase->mBase->mIdent;
|
||||||
|
@ -1754,6 +1965,25 @@ bool Declaration::ResolveTemplate(Expression* pexp, Declaration* tdec)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Declaration::ResolveTemplate(Expression* pexp, Declaration* tdec)
|
||||||
|
{
|
||||||
|
Declaration* pdec = tdec->mBase->mParams;
|
||||||
|
|
||||||
|
// Insert partially resolved templates
|
||||||
|
Declaration* ptdec = tdec->mTemplate->mParams;
|
||||||
|
while (ptdec)
|
||||||
|
{
|
||||||
|
if (ptdec->mBase)
|
||||||
|
mScope->Insert(ptdec->mIdent, ptdec->mBase);
|
||||||
|
ptdec = ptdec->mNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ResolveTemplateParameterList(pexp, pdec, true) || !ResolveTemplateParameterList(pexp, pdec, false))
|
||||||
|
return false;
|
||||||
|
|
||||||
Declaration* ppdec = nullptr;
|
Declaration* ppdec = nullptr;
|
||||||
ptdec = tdec->mTemplate->mParams;
|
ptdec = tdec->mTemplate->mParams;
|
||||||
while (ptdec)
|
while (ptdec)
|
||||||
|
@ -1796,7 +2026,7 @@ bool Declaration::CanResolveTemplate(Expression* pexp, Declaration* tdec)
|
||||||
|
|
||||||
if (pdec)
|
if (pdec)
|
||||||
{
|
{
|
||||||
if (!ResolveTemplate(ex->mDecType, pdec->mBase))
|
if (!ResolveTemplate(ex->mDecType, pdec->mBase, false, false))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (pdec->mType != DT_PACK_ARGUMENT)
|
if (pdec->mType != DT_PACK_ARGUMENT)
|
||||||
|
@ -1812,19 +2042,19 @@ bool Declaration::CanResolveTemplate(Expression* pexp, Declaration* tdec)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec)
|
bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec, bool same, bool preliminary)
|
||||||
{
|
{
|
||||||
if (tdec->IsSame(fdec))
|
if (tdec->IsSame(fdec))
|
||||||
return true;
|
return true;
|
||||||
else if (fdec->IsReference())
|
else if (fdec->IsReference())
|
||||||
return ResolveTemplate(fdec->mBase, tdec);
|
return ResolveTemplate(fdec->mBase, tdec, same, preliminary);
|
||||||
else if (tdec->mType == DT_TYPE_FUNCTION)
|
else if (tdec->mType == DT_TYPE_FUNCTION)
|
||||||
{
|
{
|
||||||
if (fdec->mType == DT_TYPE_FUNCTION)
|
if (fdec->mType == DT_TYPE_FUNCTION)
|
||||||
{
|
{
|
||||||
if (fdec->mBase)
|
if (fdec->mBase)
|
||||||
{
|
{
|
||||||
if (!tdec->mBase || !ResolveTemplate(fdec->mBase, tdec->mBase))
|
if (!tdec->mBase || !ResolveTemplate(fdec->mBase, tdec->mBase, true, preliminary))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (tdec->mBase)
|
else if (tdec->mBase)
|
||||||
|
@ -1863,7 +2093,7 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec)
|
||||||
if (!fpdec)
|
if (!fpdec)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!ResolveTemplate(fpdec->mBase, tpdec->mBase))
|
if (!ResolveTemplate(fpdec->mBase, tpdec->mBase, true, preliminary))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
fpdec = fpdec->mNext;
|
fpdec = fpdec->mNext;
|
||||||
|
@ -1879,16 +2109,16 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec)
|
||||||
}
|
}
|
||||||
else if (tdec->mType == DT_TYPE_REFERENCE)
|
else if (tdec->mType == DT_TYPE_REFERENCE)
|
||||||
{
|
{
|
||||||
return ResolveTemplate(fdec, tdec->mBase);
|
return ResolveTemplate(fdec, tdec->mBase, true, preliminary);
|
||||||
}
|
}
|
||||||
else if (tdec->mType == DT_TYPE_RVALUEREF)
|
else if (tdec->mType == DT_TYPE_RVALUEREF)
|
||||||
{
|
{
|
||||||
return ResolveTemplate(fdec, tdec->mBase);
|
return ResolveTemplate(fdec, tdec->mBase, true, preliminary);
|
||||||
}
|
}
|
||||||
else if (tdec->mType == DT_TYPE_POINTER)
|
else if (tdec->mType == DT_TYPE_POINTER)
|
||||||
{
|
{
|
||||||
if (fdec->mType == DT_TYPE_POINTER || fdec->mType == DT_TYPE_ARRAY)
|
if (fdec->mType == DT_TYPE_POINTER || fdec->mType == DT_TYPE_ARRAY)
|
||||||
return ResolveTemplate(fdec->mBase, tdec->mBase);
|
return ResolveTemplate(fdec->mBase, tdec->mBase, true, preliminary);
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1908,10 +2138,12 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec)
|
||||||
if (pdec->mType == DT_TYPE_STRUCT)
|
if (pdec->mType == DT_TYPE_STRUCT)
|
||||||
pdec = pdec->mScope->Lookup(tdec->mIdent);
|
pdec = pdec->mScope->Lookup(tdec->mIdent);
|
||||||
}
|
}
|
||||||
|
else if (preliminary && !same)
|
||||||
|
return true;
|
||||||
else
|
else
|
||||||
pdec = mScope->Insert(tdec->mIdent, fdec);
|
pdec = mScope->Insert(tdec->mIdent, fdec);
|
||||||
|
|
||||||
if (pdec && !pdec->IsSame(fdec))
|
if (pdec && !(same ? pdec->IsSame(fdec) : pdec->CanAssign(fdec)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -1952,6 +2184,21 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
else if (tdec->mType == DT_TYPE_ARRAY && fdec->mType == DT_TYPE_ARRAY && tdec->mTemplate && tdec->mBase->IsConstSame(fdec->mBase))
|
||||||
|
{
|
||||||
|
Declaration* ifdec = new Declaration(fdec->mLocation, DT_CONST_INTEGER);
|
||||||
|
ifdec->mBase = TheSignedIntTypeDeclaration;
|
||||||
|
ifdec->mSize = 2;
|
||||||
|
ifdec->mInteger = fdec->mSize / fdec->mBase->mSize;
|
||||||
|
|
||||||
|
Declaration * ipdec = mScope->Insert(tdec->mTemplate->mIdent, ifdec);
|
||||||
|
if (ipdec && !ipdec->IsSame(ifdec))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (tdec->mType == DT_TYPE_STRUCT && fdec->mType == DT_TYPE_STRUCT && tdec->mTemplate)
|
else if (tdec->mType == DT_TYPE_STRUCT && fdec->mType == DT_TYPE_STRUCT && tdec->mTemplate)
|
||||||
{
|
{
|
||||||
|
@ -2017,13 +2264,27 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec)
|
||||||
tpdec = tpdec->mNext;
|
tpdec = tpdec->mNext;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !fpdec && !tpdec;
|
if (fpdec)
|
||||||
|
return false;
|
||||||
|
else if (!tpdec)
|
||||||
|
return true;
|
||||||
|
else if (tpdec->mBase->mType == DT_PACK_TEMPLATE)
|
||||||
|
{
|
||||||
|
Declaration*tppack = new Declaration(tpdec->mLocation, DT_PACK_TYPE);
|
||||||
|
Declaration* pdec = mScope->Insert(tpdec->mBase->mIdent, tppack);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ftdec = ftdec->mNext;
|
ftdec = ftdec->mNext;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else if (!same && tdec->CanAssign(fdec))
|
||||||
|
return true;
|
||||||
else
|
else
|
||||||
return tdec->IsSame(fdec);
|
return tdec->IsSame(fdec);
|
||||||
}
|
}
|
||||||
|
@ -2036,6 +2297,8 @@ Declaration* Declaration::Clone(void)
|
||||||
ndec->mOffset = mOffset;
|
ndec->mOffset = mOffset;
|
||||||
ndec->mStride = mStride;
|
ndec->mStride = mStride;
|
||||||
ndec->mStripe = mStripe;
|
ndec->mStripe = mStripe;
|
||||||
|
ndec->mBits = mBits;
|
||||||
|
ndec->mShift = mShift;
|
||||||
ndec->mBase = mBase;
|
ndec->mBase = mBase;
|
||||||
ndec->mFlags = mFlags;
|
ndec->mFlags = mFlags;
|
||||||
ndec->mScope = mScope;
|
ndec->mScope = mScope;
|
||||||
|
@ -2055,6 +2318,7 @@ Declaration* Declaration::Clone(void)
|
||||||
ndec->mMaxValue = mMaxValue;
|
ndec->mMaxValue = mMaxValue;
|
||||||
ndec->mCompilerOptions = mCompilerOptions;
|
ndec->mCompilerOptions = mCompilerOptions;
|
||||||
ndec->mParser = mParser;
|
ndec->mParser = mParser;
|
||||||
|
ndec->mNumVars = mNumVars;
|
||||||
|
|
||||||
return ndec;
|
return ndec;
|
||||||
}
|
}
|
||||||
|
@ -2106,6 +2370,8 @@ Declaration* Declaration::ToStriped(int stripe)
|
||||||
ndec->mOffset = mOffset * stripe;
|
ndec->mOffset = mOffset * stripe;
|
||||||
ndec->mStride = mStride;
|
ndec->mStride = mStride;
|
||||||
ndec->mStripe = stripe;
|
ndec->mStripe = stripe;
|
||||||
|
ndec->mBits = mBits;
|
||||||
|
ndec->mShift = mShift;
|
||||||
ndec->mFlags = mFlags;
|
ndec->mFlags = mFlags;
|
||||||
ndec->mIdent = mIdent;
|
ndec->mIdent = mIdent;
|
||||||
ndec->mQualIdent = mQualIdent;
|
ndec->mQualIdent = mQualIdent;
|
||||||
|
@ -2133,6 +2399,24 @@ Declaration* Declaration::ToStriped(int stripe)
|
||||||
prev = pnec;
|
prev = pnec;
|
||||||
p = p->mNext;
|
p = p->mNext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Declaration* pndec = ndec->BuildPointer(mLocation);
|
||||||
|
|
||||||
|
mScope->Iterate([=](const Ident* ident, Declaration* vdec) {
|
||||||
|
if (vdec->mType == DT_CONST_FUNCTION)
|
||||||
|
{
|
||||||
|
ndec->mScope->Insert(ident, vdec->ToAlternateThis(pndec));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ndec->mDestructor = mDestructor ? mDestructor->ToAlternateThis(pndec) : nullptr;
|
||||||
|
ndec->mDefaultConstructor = mDefaultConstructor ? mDefaultConstructor->ToAlternateThis(pndec) : nullptr;
|
||||||
|
ndec->mCopyConstructor = mCopyConstructor ? mCopyConstructor->ToAlternateThis(pndec) : nullptr;
|
||||||
|
ndec->mMoveConstructor = mMoveConstructor ? mMoveConstructor->ToAlternateThis(pndec) : nullptr;
|
||||||
|
ndec->mVectorConstructor = mVectorConstructor ? mVectorConstructor->ToAlternateThis(pndec, 2) : nullptr;
|
||||||
|
ndec->mVectorDestructor = mVectorDestructor ? mVectorDestructor->ToAlternateThis(pndec, 2) : nullptr;
|
||||||
|
ndec->mVectorCopyConstructor = mVectorCopyConstructor ? mVectorCopyConstructor->ToAlternateThis(pndec, 2) : nullptr;
|
||||||
|
ndec->mVectorMoveConstructor = mVectorMoveConstructor ? mVectorMoveConstructor->ToAlternateThis(pndec, 2) : nullptr;
|
||||||
}
|
}
|
||||||
else if (mType == DT_TYPE_FUNCTION)
|
else if (mType == DT_TYPE_FUNCTION)
|
||||||
{
|
{
|
||||||
|
@ -2163,6 +2447,8 @@ Declaration* Declaration::ToVolatileType(void)
|
||||||
ndec->mSize = mSize;
|
ndec->mSize = mSize;
|
||||||
ndec->mStride = mStride;
|
ndec->mStride = mStride;
|
||||||
ndec->mBase = mBase;
|
ndec->mBase = mBase;
|
||||||
|
ndec->mBits = mBits;
|
||||||
|
ndec->mShift = mShift;
|
||||||
ndec->mFlags = mFlags | DTF_VOLATILE;
|
ndec->mFlags = mFlags | DTF_VOLATILE;
|
||||||
ndec->mScope = mScope;
|
ndec->mScope = mScope;
|
||||||
ndec->mParams = mParams;
|
ndec->mParams = mParams;
|
||||||
|
@ -2198,6 +2484,7 @@ Declaration* Declaration::ToVolatileType(void)
|
||||||
ndec->mVectorConstructor = mVectorConstructor;
|
ndec->mVectorConstructor = mVectorConstructor;
|
||||||
ndec->mVectorDestructor = mVectorDestructor;
|
ndec->mVectorDestructor = mVectorDestructor;
|
||||||
ndec->mVectorCopyConstructor = mVectorCopyConstructor;
|
ndec->mVectorCopyConstructor = mVectorCopyConstructor;
|
||||||
|
ndec->mVectorMoveConstructor = mVectorMoveConstructor;
|
||||||
ndec->mVTable = mVTable;
|
ndec->mVTable = mVTable;
|
||||||
|
|
||||||
mVolatile = ndec;
|
mVolatile = ndec;
|
||||||
|
@ -2217,7 +2504,12 @@ Declaration* Declaration::ToConstType(void)
|
||||||
ndec->mSize = mSize;
|
ndec->mSize = mSize;
|
||||||
ndec->mStride = mStride;
|
ndec->mStride = mStride;
|
||||||
ndec->mStripe = mStripe;
|
ndec->mStripe = mStripe;
|
||||||
|
if (mType == DT_TYPE_ARRAY)
|
||||||
|
ndec->mBase = mBase->ToConstType();
|
||||||
|
else
|
||||||
ndec->mBase = mBase;
|
ndec->mBase = mBase;
|
||||||
|
ndec->mBits = mBits;
|
||||||
|
ndec->mShift = mShift;
|
||||||
ndec->mFlags = mFlags | DTF_CONST;
|
ndec->mFlags = mFlags | DTF_CONST;
|
||||||
ndec->mScope = mScope;
|
ndec->mScope = mScope;
|
||||||
ndec->mParams = mParams;
|
ndec->mParams = mParams;
|
||||||
|
@ -2232,6 +2524,7 @@ Declaration* Declaration::ToConstType(void)
|
||||||
ndec->mVectorConstructor = mVectorConstructor;
|
ndec->mVectorConstructor = mVectorConstructor;
|
||||||
ndec->mVectorDestructor = mVectorDestructor;
|
ndec->mVectorDestructor = mVectorDestructor;
|
||||||
ndec->mVectorCopyConstructor = mVectorCopyConstructor;
|
ndec->mVectorCopyConstructor = mVectorCopyConstructor;
|
||||||
|
ndec->mVectorMoveConstructor = mVectorMoveConstructor;
|
||||||
ndec->mVTable = mVTable;
|
ndec->mVTable = mVTable;
|
||||||
|
|
||||||
ndec->mMutable = this;
|
ndec->mMutable = this;
|
||||||
|
@ -2241,6 +2534,35 @@ Declaration* Declaration::ToConstType(void)
|
||||||
return mConst;
|
return mConst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Declaration* Declaration::ToAlternateThis(Declaration* pthis, int nthis)
|
||||||
|
{
|
||||||
|
Declaration* ndec = this->Clone();
|
||||||
|
|
||||||
|
if (mType == DT_CONST_FUNCTION)
|
||||||
|
{
|
||||||
|
ndec->mBase = mBase->ToAlternateThis(pthis, nthis);
|
||||||
|
if (mValue)
|
||||||
|
ndec->mValue = mValue->ToAlternateThis(mBase->mParams, ndec->mBase->mParams);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Declaration* nparam = ndec->mParams->Clone();
|
||||||
|
Declaration* npp = nparam;
|
||||||
|
Declaration* kpp = ndec->mParams->mNext;
|
||||||
|
while (kpp)
|
||||||
|
{
|
||||||
|
npp->mNext = kpp->Clone();
|
||||||
|
npp = npp->mNext;
|
||||||
|
kpp = npp->mNext;
|
||||||
|
}
|
||||||
|
nparam->mBase = pthis;
|
||||||
|
if (nthis == 2)
|
||||||
|
nparam->mNext->mBase = pthis;
|
||||||
|
ndec->mParams = nparam;
|
||||||
|
}
|
||||||
|
return ndec;
|
||||||
|
}
|
||||||
|
|
||||||
Declaration* Declaration::ToMutableType(void)
|
Declaration* Declaration::ToMutableType(void)
|
||||||
{
|
{
|
||||||
if (!(mFlags & DTF_CONST))
|
if (!(mFlags & DTF_CONST))
|
||||||
|
@ -2253,7 +2575,9 @@ Declaration* Declaration::ToMutableType(void)
|
||||||
ndec->mStride = mStride;
|
ndec->mStride = mStride;
|
||||||
ndec->mStripe = mStripe;
|
ndec->mStripe = mStripe;
|
||||||
ndec->mBase = mBase;
|
ndec->mBase = mBase;
|
||||||
ndec->mFlags = mFlags | DTF_CONST;
|
ndec->mBits = mBits;
|
||||||
|
ndec->mShift = mShift;
|
||||||
|
ndec->mFlags = mFlags & ~DTF_CONST;
|
||||||
ndec->mScope = mScope;
|
ndec->mScope = mScope;
|
||||||
ndec->mParams = mParams;
|
ndec->mParams = mParams;
|
||||||
ndec->mIdent = mIdent;
|
ndec->mIdent = mIdent;
|
||||||
|
@ -2267,6 +2591,7 @@ Declaration* Declaration::ToMutableType(void)
|
||||||
ndec->mVectorConstructor = mVectorConstructor;
|
ndec->mVectorConstructor = mVectorConstructor;
|
||||||
ndec->mVectorDestructor = mVectorDestructor;
|
ndec->mVectorDestructor = mVectorDestructor;
|
||||||
ndec->mVectorCopyConstructor = mVectorCopyConstructor;
|
ndec->mVectorCopyConstructor = mVectorCopyConstructor;
|
||||||
|
ndec->mVectorMoveConstructor = mVectorMoveConstructor;
|
||||||
ndec->mVTable = mVTable;
|
ndec->mVTable = mVTable;
|
||||||
|
|
||||||
ndec->mConst = this;
|
ndec->mConst = this;
|
||||||
|
@ -2596,6 +2921,9 @@ bool Declaration::IsSame(const Declaration* dec) const
|
||||||
if (mType != dec->mType)
|
if (mType != dec->mType)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if ((mFlags & (DTF_SIGNED | DTF_CONST | DTF_VOLATILE)) != (dec->mFlags & (DTF_SIGNED | DTF_CONST | DTF_VOLATILE)))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!(mFlags & dec->mFlags & DTF_DEFINED) && mType == DT_TYPE_STRUCT)
|
if (!(mFlags & dec->mFlags & DTF_DEFINED) && mType == DT_TYPE_STRUCT)
|
||||||
return mIdent == dec->mIdent;
|
return mIdent == dec->mIdent;
|
||||||
|
|
||||||
|
@ -2604,9 +2932,6 @@ bool Declaration::IsSame(const Declaration* dec) const
|
||||||
if (mStripe != dec->mStripe)
|
if (mStripe != dec->mStripe)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ((mFlags & (DTF_SIGNED | DTF_CONST | DTF_VOLATILE)) != (dec->mFlags & (DTF_SIGNED | DTF_CONST | DTF_VOLATILE)))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (mType == DT_CONST_INTEGER)
|
if (mType == DT_CONST_INTEGER)
|
||||||
return mInteger == dec->mInteger;
|
return mInteger == dec->mInteger;
|
||||||
else if (mType == DT_TYPE_INTEGER)
|
else if (mType == DT_TYPE_INTEGER)
|
||||||
|
@ -2653,7 +2978,7 @@ bool Declaration::IsSame(const Declaration* dec) const
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (mType == DT_TYPE_TEMPLATE)
|
else if (mType == DT_TYPE_TEMPLATE || mType == DT_PACK_TEMPLATE)
|
||||||
{
|
{
|
||||||
return mIdent == dec->mIdent;
|
return mIdent == dec->mIdent;
|
||||||
}
|
}
|
||||||
|
@ -2786,7 +3111,7 @@ bool Declaration::CanAssign(const Declaration* fromType) const
|
||||||
if (mScope == fromType->mScope || (mIdent == fromType->mIdent && mSize == fromType->mSize))
|
if (mScope == fromType->mScope || (mIdent == fromType->mIdent && mSize == fromType->mSize))
|
||||||
return true;
|
return true;
|
||||||
if (fromType->mBase)
|
if (fromType->mBase)
|
||||||
return this->CanAssign(fromType->mBase);
|
return this->CanAssign(fromType->mBase->mBase);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (mType == DT_TYPE_ARRAY && fromType->mType == DT_TYPE_ARRAY)
|
else if (mType == DT_TYPE_ARRAY && fromType->mType == DT_TYPE_ARRAY)
|
||||||
|
@ -2823,6 +3148,10 @@ bool Declaration::CanAssign(const Declaration* fromType) const
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (mBase->mType == DT_TYPE_FUNCTION && fromType->mType == DT_TYPE_ASSEMBLER)
|
||||||
|
{
|
||||||
|
return (mBase->mBase->mType == DT_TYPE_VOID && !mBase->mBase->mParams);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -2849,6 +3178,52 @@ bool Declaration::IsIndexed(void) const
|
||||||
return mType == DT_TYPE_ARRAY || mType == DT_TYPE_POINTER;
|
return mType == DT_TYPE_ARRAY || mType == DT_TYPE_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Declaration::ContainsArray(void) const
|
||||||
|
{
|
||||||
|
if (mType == DT_TYPE_ARRAY)
|
||||||
|
return true;
|
||||||
|
else if (mType == DT_TYPE_STRUCT)
|
||||||
|
{
|
||||||
|
Declaration* p = mParams;
|
||||||
|
while (p)
|
||||||
|
{
|
||||||
|
if (p->mType == DT_ELEMENT && p->mBase->ContainsArray())
|
||||||
|
return true;
|
||||||
|
p = p->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Declaration::IsShortIntStruct(void) const
|
||||||
|
{
|
||||||
|
if (mType == DT_TYPE_STRUCT && mSize <= 4 && !mDestructor && !mCopyConstructor)
|
||||||
|
{
|
||||||
|
Declaration* em = mParams;
|
||||||
|
while (em)
|
||||||
|
{
|
||||||
|
if (em->mType == DT_ELEMENT && em->mBase->IsIntegerType() && em->mBits == 0)
|
||||||
|
em = em->mNext;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (strcmp(mIdent->mString, "connection")) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Declaration::HasConstructor(void) const
|
||||||
|
{
|
||||||
|
return mType == DT_TYPE_STRUCT && mScope && mScope->Lookup(mIdent->PreMangle("+"));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Declaration::IsComplexStruct(void) const
|
||||||
|
{
|
||||||
|
return mType == DT_TYPE_STRUCT && !IsShortIntStruct();
|
||||||
|
}
|
||||||
|
|
||||||
bool Declaration::IsSimpleType(void) const
|
bool Declaration::IsSimpleType(void) const
|
||||||
{
|
{
|
||||||
|
@ -2868,14 +3243,17 @@ Declaration* TheVoidFunctionTypeDeclaration, * TheConstVoidValueDeclaration;
|
||||||
Declaration* TheCharPointerTypeDeclaration, * TheConstCharPointerTypeDeclaration;
|
Declaration* TheCharPointerTypeDeclaration, * TheConstCharPointerTypeDeclaration;
|
||||||
Expression* TheVoidExpression;
|
Expression* TheVoidExpression;
|
||||||
Declaration* TheNullptrConstDeclaration, * TheZeroIntegerConstDeclaration, * TheZeroFloatConstDeclaration, * TheNullPointerTypeDeclaration;
|
Declaration* TheNullptrConstDeclaration, * TheZeroIntegerConstDeclaration, * TheZeroFloatConstDeclaration, * TheNullPointerTypeDeclaration;
|
||||||
|
Declaration* TheTrueConstDeclaration, * TheFalseConstDeclaration;
|
||||||
|
|
||||||
void InitDeclarations(void)
|
void InitDeclarations(void)
|
||||||
{
|
{
|
||||||
static Location noloc;
|
static Location noloc;
|
||||||
TheVoidTypeDeclaration = new Declaration(noloc, DT_TYPE_VOID);
|
TheVoidTypeDeclaration = new Declaration(noloc, DT_TYPE_VOID);
|
||||||
|
TheVoidTypeDeclaration->mSize = 0;
|
||||||
TheVoidTypeDeclaration->mFlags = DTF_DEFINED;
|
TheVoidTypeDeclaration->mFlags = DTF_DEFINED;
|
||||||
|
|
||||||
TheConstVoidTypeDeclaration = new Declaration(noloc, DT_TYPE_VOID);
|
TheConstVoidTypeDeclaration = new Declaration(noloc, DT_TYPE_VOID);
|
||||||
|
TheConstVoidTypeDeclaration->mSize = 0;
|
||||||
TheConstVoidTypeDeclaration->mFlags = DTF_DEFINED | DTF_CONST;
|
TheConstVoidTypeDeclaration->mFlags = DTF_DEFINED | DTF_CONST;
|
||||||
|
|
||||||
TheVoidPointerTypeDeclaration = new Declaration(noloc, DT_TYPE_POINTER);
|
TheVoidPointerTypeDeclaration = new Declaration(noloc, DT_TYPE_POINTER);
|
||||||
|
@ -2967,4 +3345,13 @@ void InitDeclarations(void)
|
||||||
TheZeroFloatConstDeclaration->mBase = TheFloatTypeDeclaration;
|
TheZeroFloatConstDeclaration->mBase = TheFloatTypeDeclaration;
|
||||||
TheZeroFloatConstDeclaration->mSize = 4;
|
TheZeroFloatConstDeclaration->mSize = 4;
|
||||||
|
|
||||||
|
TheTrueConstDeclaration = new Declaration(noloc, DT_CONST_INTEGER);
|
||||||
|
TheTrueConstDeclaration->mBase = TheBoolTypeDeclaration;
|
||||||
|
TheTrueConstDeclaration->mSize = 1;
|
||||||
|
TheTrueConstDeclaration->mInteger = 1;
|
||||||
|
|
||||||
|
TheFalseConstDeclaration = new Declaration(noloc, DT_CONST_INTEGER);
|
||||||
|
TheFalseConstDeclaration->mBase = TheBoolTypeDeclaration;
|
||||||
|
TheFalseConstDeclaration->mSize = 1;
|
||||||
|
TheFalseConstDeclaration->mInteger = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,6 +127,7 @@ static const uint64 DTF_FPARAM_UNUSED = (1ULL << 49);
|
||||||
static const uint64 DTF_DEPRECATED = (1ULL << 50);
|
static const uint64 DTF_DEPRECATED = (1ULL << 50);
|
||||||
static const uint64 DTF_FUNC_NO_RETURN = (1ULL << 51);
|
static const uint64 DTF_FUNC_NO_RETURN = (1ULL << 51);
|
||||||
static const uint64 DTF_PLACED = (1ULL << 52);
|
static const uint64 DTF_PLACED = (1ULL << 52);
|
||||||
|
static const uint64 DTF_NO_PAGE_CROSS = (1ULL << 53);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -166,6 +167,8 @@ public:
|
||||||
ScopeLevel mLevel;
|
ScopeLevel mLevel;
|
||||||
const Ident * mName;
|
const Ident * mName;
|
||||||
|
|
||||||
|
DeclarationScope* Clone(void) const;
|
||||||
|
|
||||||
DeclarationScope* mParent;
|
DeclarationScope* mParent;
|
||||||
protected:
|
protected:
|
||||||
struct Entry
|
struct Entry
|
||||||
|
@ -215,6 +218,7 @@ enum ExpressionType
|
||||||
EX_IF,
|
EX_IF,
|
||||||
EX_ELSE,
|
EX_ELSE,
|
||||||
EX_FOR,
|
EX_FOR,
|
||||||
|
EX_FORBODY,
|
||||||
EX_DO,
|
EX_DO,
|
||||||
EX_SCOPE,
|
EX_SCOPE,
|
||||||
EX_BREAK,
|
EX_BREAK,
|
||||||
|
@ -238,9 +242,16 @@ enum ExpressionType
|
||||||
EX_PACK,
|
EX_PACK,
|
||||||
EX_PACK_TYPE,
|
EX_PACK_TYPE,
|
||||||
EX_LABEL,
|
EX_LABEL,
|
||||||
EX_GOTO
|
EX_GOTO,
|
||||||
|
EX_AGGREGATE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const uint32 ANAFL_LHS = (1U << 0);
|
||||||
|
static const uint32 ANAFL_RHS = (1U << 1);
|
||||||
|
static const uint32 ANAFL_ASSIGN = (1U << 2);
|
||||||
|
static const uint32 ANAFL_ALIAS = (1U << 3);
|
||||||
|
|
||||||
|
|
||||||
class Expression
|
class Expression
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -257,12 +268,16 @@ public:
|
||||||
AsmInsType mAsmInsType;
|
AsmInsType mAsmInsType;
|
||||||
AsmInsMode mAsmInsMode;
|
AsmInsMode mAsmInsMode;
|
||||||
bool mConst;
|
bool mConst;
|
||||||
|
uint32 mFlags;
|
||||||
|
|
||||||
Expression* LogicInvertExpression(void);
|
Expression* LogicInvertExpression(void);
|
||||||
Expression* ConstantFold(Errors * errors, LinkerSection* dataSection, Linker * linker = nullptr);
|
Expression* ConstantFold(Errors * errors, LinkerSection* dataSection, Linker * linker = nullptr);
|
||||||
Expression* ConstantDereference(Errors* errors, LinkerSection* dataSection);
|
Expression* ConstantDereference(Errors* errors, LinkerSection* dataSection);
|
||||||
bool HasSideEffects(void) const;
|
bool HasSideEffects(void) const;
|
||||||
Expression* ListAppend(Expression* lexp);
|
Expression* ListAppend(Expression* lexp);
|
||||||
|
Expression* ToAlternateThis(Declaration* pthis, Declaration* nthis);
|
||||||
|
|
||||||
|
void ReplaceVariable(Declaration* pvar, Declaration* nvar);
|
||||||
|
|
||||||
bool IsSame(const Expression* exp) const;
|
bool IsSame(const Expression* exp) const;
|
||||||
bool IsRValue(void) const;
|
bool IsRValue(void) const;
|
||||||
|
@ -270,6 +285,7 @@ public:
|
||||||
bool IsConstRef(void) const;
|
bool IsConstRef(void) const;
|
||||||
bool IsVolatile(void) const;
|
bool IsVolatile(void) const;
|
||||||
|
|
||||||
|
|
||||||
void Dump(int ident) const;
|
void Dump(int ident) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -286,7 +302,7 @@ public:
|
||||||
Token mToken;
|
Token mToken;
|
||||||
Declaration * mBase, * mParams, * mParamPack, * mNext, * mPrev, * mConst, * mMutable, * mVolatile;
|
Declaration * mBase, * mParams, * mParamPack, * mNext, * mPrev, * mConst, * mMutable, * mVolatile;
|
||||||
Declaration * mDefaultConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment, * mMoveConstructor, * mMoveAssignment;
|
Declaration * mDefaultConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment, * mMoveConstructor, * mMoveAssignment;
|
||||||
Declaration * mVectorConstructor, * mVectorDestructor, * mVectorCopyConstructor, * mVectorCopyAssignment;
|
Declaration * mVectorConstructor, * mVectorDestructor, * mVectorCopyConstructor, * mVectorCopyAssignment, * mVectorMoveConstructor, * mVectorMoveAssignment;
|
||||||
Declaration * mVTable, * mClass, * mTemplate;
|
Declaration * mVTable, * mClass, * mTemplate;
|
||||||
Declaration * mForwardParam, * mForwardCall;
|
Declaration * mForwardParam, * mForwardCall;
|
||||||
|
|
||||||
|
@ -328,12 +344,17 @@ public:
|
||||||
bool IsSimpleType(void) const;
|
bool IsSimpleType(void) const;
|
||||||
bool IsReference(void) const;
|
bool IsReference(void) const;
|
||||||
bool IsIndexed(void) const;
|
bool IsIndexed(void) const;
|
||||||
|
bool ContainsArray(void) const;
|
||||||
|
bool IsShortIntStruct(void) const;
|
||||||
|
bool IsComplexStruct(void) const;
|
||||||
|
bool HasConstructor(void) const;
|
||||||
|
|
||||||
void SetDefined(void);
|
void SetDefined(void);
|
||||||
|
|
||||||
Declaration* ToConstType(void);
|
Declaration* ToConstType(void);
|
||||||
Declaration* ToMutableType(void);
|
Declaration* ToMutableType(void);
|
||||||
Declaration* ToVolatileType(void);
|
Declaration* ToVolatileType(void);
|
||||||
|
Declaration* ToAlternateThis(Declaration* pthis, int nthis = 1);
|
||||||
|
|
||||||
Declaration* ToStriped(int stripe);
|
Declaration* ToStriped(int stripe);
|
||||||
Declaration* ToStriped(Errors* errors);
|
Declaration* ToStriped(Errors* errors);
|
||||||
|
@ -357,8 +378,9 @@ public:
|
||||||
DecType ValueType(void) const;
|
DecType ValueType(void) const;
|
||||||
|
|
||||||
bool CanResolveTemplate(Expression* pexp, Declaration* tdec);
|
bool CanResolveTemplate(Expression* pexp, Declaration* tdec);
|
||||||
bool ResolveTemplate(Declaration* fdec, Declaration * tdec);
|
bool ResolveTemplate(Declaration* fdec, Declaration * tdec, bool same, bool preliminary);
|
||||||
bool ResolveTemplate(Expression* pexp, Declaration* tdec);
|
bool ResolveTemplate(Expression* pexp, Declaration* tdec);
|
||||||
|
bool ResolveTemplateParameterList(Expression* pexp, Declaration* pdec, bool preliminary);
|
||||||
|
|
||||||
Declaration* ExpandTemplate(DeclarationScope* scope);
|
Declaration* ExpandTemplate(DeclarationScope* scope);
|
||||||
|
|
||||||
|
@ -376,5 +398,6 @@ extern Declaration* TheBoolTypeDeclaration, * TheFloatTypeDeclaration, * TheVoid
|
||||||
extern Declaration* TheVoidFunctionTypeDeclaration, * TheConstVoidValueDeclaration;
|
extern Declaration* TheVoidFunctionTypeDeclaration, * TheConstVoidValueDeclaration;
|
||||||
extern Declaration* TheCharPointerTypeDeclaration, * TheConstCharPointerTypeDeclaration;
|
extern Declaration* TheCharPointerTypeDeclaration, * TheConstCharPointerTypeDeclaration;
|
||||||
extern Declaration* TheNullptrConstDeclaration, * TheZeroIntegerConstDeclaration, * TheZeroFloatConstDeclaration, * TheNullPointerTypeDeclaration;
|
extern Declaration* TheNullptrConstDeclaration, * TheZeroIntegerConstDeclaration, * TheZeroFloatConstDeclaration, * TheNullPointerTypeDeclaration;
|
||||||
|
extern Declaration* TheTrueConstDeclaration, * TheFalseConstDeclaration;
|
||||||
extern Expression* TheVoidExpression;
|
extern Expression* TheVoidExpression;
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,18 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
Errors::Errors(void)
|
Errors::Errors(void)
|
||||||
: mErrorCount(0)
|
: mErrorCount(0), mMinLevel(EINFO_GENERIC), mDisabled(EERR_GENERIC)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorID Errors::SetMinLevel(ErrorID id)
|
||||||
|
{
|
||||||
|
ErrorID pid = mMinLevel;
|
||||||
|
mMinLevel = id;
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const Ident* info1, const Ident* info2)
|
void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const Ident* info1, const Ident* info2)
|
||||||
{
|
{
|
||||||
if (!info1)
|
if (!info1)
|
||||||
|
@ -22,6 +29,8 @@ void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const Iden
|
||||||
|
|
||||||
void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const char* info1, const char * info2)
|
void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const char* info1, const char * info2)
|
||||||
{
|
{
|
||||||
|
if (eid >= mMinLevel && !(eid < EERR_GENERIC && mDisabled[eid]))
|
||||||
|
{
|
||||||
const char* level = "info";
|
const char* level = "info";
|
||||||
if (eid >= EERR_GENERIC)
|
if (eid >= EERR_GENERIC)
|
||||||
{
|
{
|
||||||
|
@ -57,6 +66,7 @@ void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const char
|
||||||
|
|
||||||
if (mErrorCount > 10 || eid >= EFATAL_GENERIC)
|
if (mErrorCount > 10 || eid >= EFATAL_GENERIC)
|
||||||
exit(20);
|
exit(20);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "NumberSet.h"
|
||||||
|
|
||||||
|
|
||||||
class Location
|
class Location
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -10,7 +13,11 @@ public:
|
||||||
Location() : mFileName(nullptr), mLine(0), mColumn(0), mFrom(nullptr) {}
|
Location() : mFileName(nullptr), mLine(0), mColumn(0), mFrom(nullptr) {}
|
||||||
Location(const Location& loc, const Location* from)
|
Location(const Location& loc, const Location* from)
|
||||||
: mFileName(loc.mFileName), mLine(loc.mLine), mColumn(loc.mColumn), mFrom(from)
|
: mFileName(loc.mFileName), mLine(loc.mLine), mColumn(loc.mColumn), mFrom(from)
|
||||||
{}
|
{
|
||||||
|
static volatile int k;
|
||||||
|
if (from)
|
||||||
|
k = from->mLine;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Ident;
|
class Ident;
|
||||||
|
@ -44,6 +51,8 @@ enum ErrorID
|
||||||
EWARN_DEFAULT_COPY_DEPRECATED,
|
EWARN_DEFAULT_COPY_DEPRECATED,
|
||||||
EWARN_INSUFFICIENT_MEMORY,
|
EWARN_INSUFFICIENT_MEMORY,
|
||||||
EWARN_FUNCTION_NOT_INLINED,
|
EWARN_FUNCTION_NOT_INLINED,
|
||||||
|
EWARN_INVALID_VOID_POINTER_ARITHMETIC,
|
||||||
|
EWARN_DIVISION_BY_ZERO,
|
||||||
|
|
||||||
EERR_GENERIC = 3000,
|
EERR_GENERIC = 3000,
|
||||||
EERR_FILE_NOT_FOUND,
|
EERR_FILE_NOT_FOUND,
|
||||||
|
@ -103,7 +112,7 @@ enum ErrorID
|
||||||
ERRR_INSTANTIATE_ABSTRACT_CLASS,
|
ERRR_INSTANTIATE_ABSTRACT_CLASS,
|
||||||
ERRR_INVALID_GOTO,
|
ERRR_INVALID_GOTO,
|
||||||
EERR_INVALID_INITIALIZER,
|
EERR_INVALID_INITIALIZER,
|
||||||
|
ERRR_INVALID_VOID_POINTER_ARITHMETIC,
|
||||||
|
|
||||||
EERR_INVALID_CONSTEXPR,
|
EERR_INVALID_CONSTEXPR,
|
||||||
EERR_DOUBLE_FREE,
|
EERR_DOUBLE_FREE,
|
||||||
|
@ -118,9 +127,13 @@ enum ErrorID
|
||||||
EERR_INVALID_CLASS_INITIALIZER,
|
EERR_INVALID_CLASS_INITIALIZER,
|
||||||
EERR_CALL_OF_DELETED_FUNCTION,
|
EERR_CALL_OF_DELETED_FUNCTION,
|
||||||
|
|
||||||
|
EERR_STATIC_ASSERT,
|
||||||
|
|
||||||
EFATAL_GENERIC = 4000,
|
EFATAL_GENERIC = 4000,
|
||||||
EFATAL_OUT_OF_MEMORY,
|
EFATAL_OUT_OF_MEMORY,
|
||||||
EFATAL_MACRO_EXPANSION_DEPTH,
|
EFATAL_MACRO_EXPANSION_DEPTH,
|
||||||
|
|
||||||
|
ERROR_MAX = 5000
|
||||||
};
|
};
|
||||||
|
|
||||||
class Errors
|
class Errors
|
||||||
|
@ -128,7 +141,12 @@ class Errors
|
||||||
public:
|
public:
|
||||||
Errors(void);
|
Errors(void);
|
||||||
|
|
||||||
|
ErrorID SetMinLevel(ErrorID id);
|
||||||
|
|
||||||
int mErrorCount;
|
int mErrorCount;
|
||||||
|
ErrorID mMinLevel;
|
||||||
|
|
||||||
|
NumberSet mDisabled;
|
||||||
|
|
||||||
void Error(const Location& loc, ErrorID eid, const char* msg, const Ident* info1, const Ident* info2 = nullptr);
|
void Error(const Location& loc, ErrorID eid, const char* msg, const Ident* info1, const Ident* info2 = nullptr);
|
||||||
void Error(const Location& loc, ErrorID eid, const char* msg, const char* info1 = nullptr, const char* info2 = nullptr);
|
void Error(const Location& loc, ErrorID eid, const char* msg, const char* info1 = nullptr, const char* info2 = nullptr);
|
||||||
|
|
|
@ -393,7 +393,7 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head)
|
||||||
|
|
||||||
if (procDec->mValue && procDec->mValue->mType == EX_DISPATCH)
|
if (procDec->mValue && procDec->mValue->mType == EX_DISPATCH)
|
||||||
{
|
{
|
||||||
Declaration* maxf = nullptr;
|
Declaration* maxf = nullptr, * reff = nullptr;
|
||||||
|
|
||||||
bool stackCall = false;
|
bool stackCall = false;
|
||||||
|
|
||||||
|
@ -402,7 +402,10 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head)
|
||||||
Declaration* cf = procDec->mCalled[i];
|
Declaration* cf = procDec->mCalled[i];
|
||||||
|
|
||||||
if (cf->mBase->mFlags & DTF_STACKCALL)
|
if (cf->mBase->mFlags & DTF_STACKCALL)
|
||||||
|
{
|
||||||
stackCall = true;
|
stackCall = true;
|
||||||
|
reff = cf;
|
||||||
|
}
|
||||||
|
|
||||||
if (!maxf)
|
if (!maxf)
|
||||||
maxf = cf;
|
maxf = cf;
|
||||||
|
@ -410,6 +413,9 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head)
|
||||||
maxf = cf;
|
maxf = cf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!reff)
|
||||||
|
reff = maxf;
|
||||||
|
|
||||||
for (int i = 0; i < procDec->mCalled.Size(); i++)
|
for (int i = 0; i < procDec->mCalled.Size(); i++)
|
||||||
{
|
{
|
||||||
Declaration* cf = procDec->mCalled[i];
|
Declaration* cf = procDec->mCalled[i];
|
||||||
|
@ -420,9 +426,9 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head)
|
||||||
cf->mBase->mFlags |= DTF_STACKCALL;
|
cf->mBase->mFlags |= DTF_STACKCALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cf != maxf)
|
if (cf != reff)
|
||||||
{
|
{
|
||||||
Declaration* fp = cf->mBase->mParams, * mp = maxf->mBase->mParams;
|
Declaration* fp = cf->mBase->mParams, * mp = reff->mBase->mParams;
|
||||||
while (fp)
|
while (fp)
|
||||||
{
|
{
|
||||||
fp->mVarIndex = mp->mVarIndex;
|
fp->mVarIndex = mp->mVarIndex;
|
||||||
|
@ -431,10 +437,11 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!mp);
|
assert(!mp);
|
||||||
|
|
||||||
cf->mBase->mFastCallBase = cf->mFastCallBase = maxf->mBase->mFastCallBase;
|
|
||||||
cf->mBase->mFastCallSize = cf->mFastCallSize = maxf->mBase->mFastCallSize;
|
cf->mBase->mFastCallSize = cf->mFastCallSize = maxf->mBase->mFastCallSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cf != maxf)
|
||||||
|
cf->mBase->mFastCallBase = cf->mFastCallBase = maxf->mBase->mFastCallBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
procDec->mFastCallBase = procDec->mBase->mFastCallBase;
|
procDec->mFastCallBase = procDec->mBase->mFastCallBase;
|
||||||
|
@ -474,7 +481,7 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head)
|
||||||
fplimit += 256;
|
fplimit += 256;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (procDec->mBase->mBase->mType == DT_TYPE_STRUCT)
|
if (procDec->mBase->mBase->IsComplexStruct())
|
||||||
{
|
{
|
||||||
if (nbase < numfpzero && nbase + 2 > numfpzero)
|
if (nbase < numfpzero && nbase + 2 > numfpzero)
|
||||||
nbase = numfpzero;
|
nbase = numfpzero;
|
||||||
|
@ -658,7 +665,7 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* cexp, Expression* exp, Declara
|
||||||
if (mCompilerOptions & COPT_OPTIMIZE_CONST_EXPRESSIONS)
|
if (mCompilerOptions & COPT_OPTIMIZE_CONST_EXPRESSIONS)
|
||||||
dec->mFlags |= DTF_FUNC_CONSTEXPR;
|
dec->mFlags |= DTF_FUNC_CONSTEXPR;
|
||||||
dec->mFlags |= DTF_FUNC_PURE;
|
dec->mFlags |= DTF_FUNC_PURE;
|
||||||
Analyze(exp, dec, false, false);
|
Analyze(exp, dec, 0);
|
||||||
|
|
||||||
Declaration* pdec = dec->mBase->mParams;
|
Declaration* pdec = dec->mBase->mParams;
|
||||||
int vi = 0;
|
int vi = 0;
|
||||||
|
@ -678,7 +685,7 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* cexp, Expression* exp, Declara
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mErrors->Error(dec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", dec->mQualIdent);
|
mErrors->Error(dec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", dec->FullIdent());
|
||||||
if (cexp)
|
if (cexp)
|
||||||
mErrors->Error(cexp->mLocation, EINFO_CALLED_FROM, "Called from here");
|
mErrors->Error(cexp->mLocation, EINFO_CALLED_FROM, "Called from here");
|
||||||
|
|
||||||
|
@ -754,7 +761,7 @@ void GlobalAnalyzer::AnalyzeGlobalVariable(Declaration* dec)
|
||||||
|
|
||||||
if (dec->mValue)
|
if (dec->mValue)
|
||||||
{
|
{
|
||||||
Analyze(dec->mValue, dec, false, false);
|
Analyze(dec->mValue, dec, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -764,17 +771,19 @@ void GlobalAnalyzer::AnalyzeInit(Declaration* mdec)
|
||||||
while (mdec)
|
while (mdec)
|
||||||
{
|
{
|
||||||
if (mdec->mValue)
|
if (mdec->mValue)
|
||||||
RegisterProc(Analyze(mdec->mValue, mdec, false, false));
|
RegisterProc(Analyze(mdec->mValue, mdec, 0));
|
||||||
else if (mdec->mParams)
|
else if (mdec->mParams)
|
||||||
AnalyzeInit(mdec->mParams);
|
AnalyzeInit(mdec->mParams);
|
||||||
mdec = mdec->mNext;
|
mdec = mdec->mNext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, bool lhs, bool aliasing)
|
Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, uint32 flags)
|
||||||
{
|
{
|
||||||
Declaration* ldec, * rdec;
|
Declaration* ldec, * rdec;
|
||||||
|
|
||||||
|
exp->mFlags = flags;
|
||||||
|
|
||||||
switch (exp->mType)
|
switch (exp->mType)
|
||||||
{
|
{
|
||||||
case EX_ERROR:
|
case EX_ERROR:
|
||||||
|
@ -792,7 +801,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
||||||
}
|
}
|
||||||
else if (exp->mDecValue->mType == DT_CONST_POINTER)
|
else if (exp->mDecValue->mType == DT_CONST_POINTER)
|
||||||
{
|
{
|
||||||
ldec = Analyze(exp->mDecValue->mValue, procDec, true, true);
|
ldec = Analyze(exp->mDecValue->mValue, procDec, ANAFL_LHS | ANAFL_ALIAS);
|
||||||
if (ldec->mType == DT_VARIABLE)
|
if (ldec->mType == DT_VARIABLE)
|
||||||
ldec->mFlags |= DTF_VAR_ALIASING;
|
ldec->mFlags |= DTF_VAR_ALIASING;
|
||||||
RegisterProc(ldec);
|
RegisterProc(ldec);
|
||||||
|
@ -816,7 +825,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
||||||
if (mCompilerOptions & COPT_DEBUGINFO)
|
if (mCompilerOptions & COPT_DEBUGINFO)
|
||||||
exp->mDecValue->mReferences.Push(exp);
|
exp->mDecValue->mReferences.Push(exp);
|
||||||
|
|
||||||
if (aliasing)
|
if (flags & ANAFL_ALIAS)
|
||||||
{
|
{
|
||||||
Declaration* dec = exp->mDecValue;
|
Declaration* dec = exp->mDecValue;
|
||||||
while (dec->mType == DT_VARIABLE_REF)
|
while (dec->mType == DT_VARIABLE_REF)
|
||||||
|
@ -833,14 +842,14 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
||||||
if (!(type->mFlags & DTF_CONST))
|
if (!(type->mFlags & DTF_CONST))
|
||||||
procDec->mFlags &= ~DTF_FUNC_CONSTEXPR;
|
procDec->mFlags &= ~DTF_FUNC_CONSTEXPR;
|
||||||
|
|
||||||
if (lhs)
|
if (flags & ANAFL_LHS)
|
||||||
procDec->mFlags &= ~DTF_FUNC_PURE;
|
procDec->mFlags &= ~DTF_FUNC_PURE;
|
||||||
|
|
||||||
AnalyzeGlobalVariable(exp->mDecValue);
|
AnalyzeGlobalVariable(exp->mDecValue);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (lhs)
|
if (flags & ANAFL_LHS)
|
||||||
exp->mDecValue->mFlags |= DTF_VAR_ADDRESS;
|
exp->mDecValue->mFlags |= DTF_VAR_ADDRESS;
|
||||||
|
|
||||||
if (!(exp->mDecValue->mFlags & DTF_ANALYZED))
|
if (!(exp->mDecValue->mFlags & DTF_ANALYZED))
|
||||||
|
@ -854,8 +863,8 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
||||||
case EX_ASSIGNMENT:
|
case EX_ASSIGNMENT:
|
||||||
procDec->mComplexity += 5 * exp->mLeft->mDecType->mSize;
|
procDec->mComplexity += 5 * exp->mLeft->mDecType->mSize;
|
||||||
|
|
||||||
ldec = Analyze(exp->mLeft, procDec, true, false);
|
ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_RHS);
|
||||||
rdec = Analyze(exp->mRight, procDec, false, false);
|
rdec = Analyze(exp->mRight, procDec, ANAFL_RHS);
|
||||||
if (exp->mLeft->mType == EX_VARIABLE && exp->mRight->mType == EX_CALL && exp->mLeft->mDecType->mType == DT_TYPE_STRUCT)
|
if (exp->mLeft->mType == EX_VARIABLE && exp->mRight->mType == EX_CALL && exp->mLeft->mDecType->mType == DT_TYPE_STRUCT)
|
||||||
exp->mLeft->mDecValue->mFlags |= DTF_VAR_ALIASING;
|
exp->mLeft->mDecValue->mFlags |= DTF_VAR_ALIASING;
|
||||||
RegisterProc(rdec);
|
RegisterProc(rdec);
|
||||||
|
@ -864,33 +873,33 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
||||||
case EX_BINARY:
|
case EX_BINARY:
|
||||||
procDec->mComplexity += 10 * exp->mDecType->mSize;
|
procDec->mComplexity += 10 * exp->mDecType->mSize;
|
||||||
|
|
||||||
ldec = Analyze(exp->mLeft, procDec, lhs, false);
|
ldec = Analyze(exp->mLeft, procDec, flags & ~ANAFL_ALIAS);
|
||||||
rdec = Analyze(exp->mRight, procDec, lhs, false);
|
rdec = Analyze(exp->mRight, procDec, flags & ~ANAFL_ALIAS);
|
||||||
return ldec;
|
return ldec;
|
||||||
|
|
||||||
case EX_RELATIONAL:
|
case EX_RELATIONAL:
|
||||||
procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize;
|
procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize;
|
||||||
|
|
||||||
ldec = Analyze(exp->mLeft, procDec, false, false);
|
ldec = Analyze(exp->mLeft, procDec, ANAFL_RHS);
|
||||||
rdec = Analyze(exp->mRight, procDec, false, false);
|
rdec = Analyze(exp->mRight, procDec, ANAFL_RHS);
|
||||||
return TheBoolTypeDeclaration;
|
return TheBoolTypeDeclaration;
|
||||||
|
|
||||||
case EX_PREINCDEC:
|
case EX_PREINCDEC:
|
||||||
procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize;
|
procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize;
|
||||||
|
|
||||||
return Analyze(exp->mLeft, procDec, true, false);
|
return Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_RHS);
|
||||||
case EX_PREFIX:
|
case EX_PREFIX:
|
||||||
if (exp->mToken == TK_BINARY_AND)
|
if (exp->mToken == TK_BINARY_AND)
|
||||||
{
|
{
|
||||||
ldec = Analyze(exp->mLeft, procDec, true, true);
|
ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_ALIAS);
|
||||||
if (ldec->mType == DT_VARIABLE)
|
if (ldec->mType == DT_VARIABLE)
|
||||||
ldec->mFlags |= DTF_VAR_ALIASING;
|
ldec->mFlags |= DTF_VAR_ALIASING;
|
||||||
}
|
}
|
||||||
else if (exp->mToken == TK_MUL)
|
else if (exp->mToken == TK_MUL)
|
||||||
{
|
{
|
||||||
ldec = Analyze(exp->mLeft, procDec, false, false);
|
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||||
procDec->mFlags &= ~DTF_FUNC_CONSTEXPR;
|
procDec->mFlags &= ~DTF_FUNC_CONSTEXPR;
|
||||||
if (lhs)
|
if (flags & ANAFL_LHS)
|
||||||
procDec->mFlags &= ~DTF_FUNC_PURE;
|
procDec->mFlags &= ~DTF_FUNC_PURE;
|
||||||
|
|
||||||
return exp->mDecType;
|
return exp->mDecType;
|
||||||
|
@ -899,10 +908,14 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
||||||
{
|
{
|
||||||
return TheUnsignedCharTypeDeclaration;
|
return TheUnsignedCharTypeDeclaration;
|
||||||
}
|
}
|
||||||
|
else if (exp->mToken == TK_SIZEOF)
|
||||||
|
{
|
||||||
|
return TheUnsignedIntTypeDeclaration;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize;
|
procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize;
|
||||||
return Analyze(exp->mLeft, procDec, false, false);
|
return Analyze(exp->mLeft, procDec, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EX_POSTFIX:
|
case EX_POSTFIX:
|
||||||
|
@ -911,31 +924,31 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
||||||
case EX_POSTINCDEC:
|
case EX_POSTINCDEC:
|
||||||
procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize;
|
procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize;
|
||||||
|
|
||||||
return Analyze(exp->mLeft, procDec, true, false);
|
return Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_RHS);
|
||||||
case EX_INDEX:
|
case EX_INDEX:
|
||||||
procDec->mComplexity += 10 * exp->mRight->mDecType->mSize;
|
procDec->mComplexity += 10 * exp->mRight->mDecType->mSize;
|
||||||
|
|
||||||
ldec = Analyze(exp->mLeft, procDec, lhs, false);
|
ldec = Analyze(exp->mLeft, procDec, flags & ~ANAFL_ALIAS);
|
||||||
if (ldec->mType == DT_VARIABLE || ldec->mType == DT_ARGUMENT)
|
if (ldec->mType == DT_VARIABLE || ldec->mType == DT_ARGUMENT)
|
||||||
{
|
{
|
||||||
ldec = ldec->mBase;
|
ldec = ldec->mBase;
|
||||||
if (ldec->mType == DT_TYPE_POINTER)
|
if (ldec->mType == DT_TYPE_POINTER)
|
||||||
{
|
{
|
||||||
if (lhs)
|
if (flags & ANAFL_LHS)
|
||||||
procDec->mFlags &= ~DTF_FUNC_PURE;
|
procDec->mFlags &= ~DTF_FUNC_PURE;
|
||||||
procDec->mFlags &= ~DTF_FUNC_CONSTEXPR;
|
procDec->mFlags &= ~DTF_FUNC_CONSTEXPR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rdec = Analyze(exp->mRight, procDec, false, false);
|
rdec = Analyze(exp->mRight, procDec, 0);
|
||||||
if (ldec->mBase)
|
if (ldec->mBase)
|
||||||
return ldec->mBase;
|
return ldec->mBase;
|
||||||
break;
|
break;
|
||||||
case EX_QUALIFY:
|
case EX_QUALIFY:
|
||||||
Analyze(exp->mLeft, procDec, lhs, aliasing);
|
Analyze(exp->mLeft, procDec, flags);
|
||||||
return exp->mDecValue->mBase;
|
return exp->mDecValue->mBase;
|
||||||
case EX_DISPATCH:
|
case EX_DISPATCH:
|
||||||
procDec->mFlags |= DTF_PREVENT_INLINE;
|
procDec->mFlags |= DTF_PREVENT_INLINE;
|
||||||
Analyze(exp->mLeft, procDec, lhs, false);
|
Analyze(exp->mLeft, procDec, flags & ~ANAFL_ALIAS);
|
||||||
// RegisterCall(procDec, exp->mLeft->mDecType);
|
// RegisterCall(procDec, exp->mLeft->mDecType);
|
||||||
break;
|
break;
|
||||||
case EX_VCALL:
|
case EX_VCALL:
|
||||||
|
@ -946,7 +959,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
||||||
case EX_INLINE:
|
case EX_INLINE:
|
||||||
procDec->mComplexity += 10;
|
procDec->mComplexity += 10;
|
||||||
|
|
||||||
ldec = Analyze(exp->mLeft, procDec, false, false);
|
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||||
if ((ldec->mFlags & DTF_INTRINSIC) && !ldec->mValue)
|
if ((ldec->mFlags & DTF_INTRINSIC) && !ldec->mValue)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -1033,7 +1046,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
||||||
if (pex->mType == EX_CALL && IsStackParam(pex->mDecType) && !(pdec && (pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF)))
|
if (pex->mType == EX_CALL && IsStackParam(pex->mDecType) && !(pdec && (pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF)))
|
||||||
ldec->mBase->mFlags |= DTF_STACKCALL;
|
ldec->mBase->mFlags |= DTF_STACKCALL;
|
||||||
|
|
||||||
RegisterProc(Analyze(pex, procDec, pdec && pdec->mBase->IsReference(), false));
|
RegisterProc(Analyze(pex, procDec, (pdec && pdec->mBase->IsReference()) ? ANAFL_LHS : 0));
|
||||||
|
|
||||||
if (pdec)
|
if (pdec)
|
||||||
pdec = pdec->mNext;
|
pdec = pdec->mNext;
|
||||||
|
@ -1047,12 +1060,12 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
||||||
break;
|
break;
|
||||||
case EX_LIST:
|
case EX_LIST:
|
||||||
case EX_COMMA:
|
case EX_COMMA:
|
||||||
RegisterProc(Analyze(exp->mLeft, procDec, false, false));
|
RegisterProc(Analyze(exp->mLeft, procDec, 0));
|
||||||
return Analyze(exp->mRight, procDec, false, false);
|
return Analyze(exp->mRight, procDec, 0);
|
||||||
case EX_RETURN:
|
case EX_RETURN:
|
||||||
if (exp->mLeft)
|
if (exp->mLeft)
|
||||||
{
|
{
|
||||||
RegisterProc(Analyze(exp->mLeft, procDec, procDec->mBase->mBase->IsReference(), false));
|
RegisterProc(Analyze(exp->mLeft, procDec, procDec->mBase->mBase->IsReference() ? ANAFL_LHS : 0));
|
||||||
if (procDec->mBase->mBase && procDec->mBase->mBase->mType == DT_TYPE_STRUCT && procDec->mBase->mBase->mCopyConstructor)
|
if (procDec->mBase->mBase && procDec->mBase->mBase->mType == DT_TYPE_STRUCT && procDec->mBase->mBase->mCopyConstructor)
|
||||||
{
|
{
|
||||||
if (procDec->mBase->mBase->mMoveConstructor)
|
if (procDec->mBase->mBase->mMoveConstructor)
|
||||||
|
@ -1073,47 +1086,47 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
||||||
if (exp->mType == EX_SEQUENCE)
|
if (exp->mType == EX_SEQUENCE)
|
||||||
{
|
{
|
||||||
if (exp->mLeft)
|
if (exp->mLeft)
|
||||||
ldec = Analyze(exp->mLeft, procDec, false, false);
|
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||||
exp = exp->mRight;
|
exp = exp->mRight;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return Analyze(exp, procDec, false, false);
|
return Analyze(exp, procDec, 0);
|
||||||
|
|
||||||
} while (exp);
|
} while (exp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EX_SCOPE:
|
case EX_SCOPE:
|
||||||
Analyze(exp->mLeft, procDec, false, false);
|
Analyze(exp->mLeft, procDec, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EX_CONSTRUCT:
|
case EX_CONSTRUCT:
|
||||||
if (exp->mLeft->mLeft)
|
if (exp->mLeft->mLeft)
|
||||||
Analyze(exp->mLeft->mLeft, procDec, false, false);
|
Analyze(exp->mLeft->mLeft, procDec, 0);
|
||||||
if (exp->mLeft->mRight)
|
if (exp->mLeft->mRight)
|
||||||
Analyze(exp->mLeft->mRight, procDec, false, false);
|
Analyze(exp->mLeft->mRight, procDec, 0);
|
||||||
if (exp->mRight)
|
if (exp->mRight)
|
||||||
return Analyze(exp->mRight, procDec, false, false);
|
return Analyze(exp->mRight, procDec, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EX_CLEANUP:
|
case EX_CLEANUP:
|
||||||
Analyze(exp->mRight, procDec, false, false);
|
Analyze(exp->mRight, procDec, 0);
|
||||||
return Analyze(exp->mLeft, procDec, lhs, false);
|
return Analyze(exp->mLeft, procDec, flags & ~ANAFL_ALIAS);
|
||||||
|
|
||||||
case EX_WHILE:
|
case EX_WHILE:
|
||||||
procDec->mFlags &= ~DTF_FUNC_CONSTEXPR;
|
procDec->mFlags &= ~DTF_FUNC_CONSTEXPR;
|
||||||
|
|
||||||
procDec->mComplexity += 20;
|
procDec->mComplexity += 20;
|
||||||
|
|
||||||
ldec = Analyze(exp->mLeft, procDec, false, false);
|
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||||
rdec = Analyze(exp->mRight, procDec, false, false);
|
rdec = Analyze(exp->mRight, procDec, 0);
|
||||||
break;
|
break;
|
||||||
case EX_IF:
|
case EX_IF:
|
||||||
procDec->mComplexity += 20;
|
procDec->mComplexity += 20;
|
||||||
|
|
||||||
ldec = Analyze(exp->mLeft, procDec, false, false);
|
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||||
rdec = Analyze(exp->mRight->mLeft, procDec, false, false);
|
rdec = Analyze(exp->mRight->mLeft, procDec, 0);
|
||||||
if (exp->mRight->mRight)
|
if (exp->mRight->mRight)
|
||||||
rdec = Analyze(exp->mRight->mRight, procDec, false, false);
|
rdec = Analyze(exp->mRight->mRight, procDec, 0);
|
||||||
break;
|
break;
|
||||||
case EX_ELSE:
|
case EX_ELSE:
|
||||||
break;
|
break;
|
||||||
|
@ -1123,18 +1136,23 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
||||||
procDec->mComplexity += 30;
|
procDec->mComplexity += 30;
|
||||||
|
|
||||||
if (exp->mLeft->mRight)
|
if (exp->mLeft->mRight)
|
||||||
ldec = Analyze(exp->mLeft->mRight, procDec, false, false);
|
ldec = Analyze(exp->mLeft->mRight, procDec, 0);
|
||||||
if (exp->mLeft->mLeft->mLeft)
|
if (exp->mLeft->mLeft->mLeft)
|
||||||
ldec = Analyze(exp->mLeft->mLeft->mLeft, procDec, false, false);
|
ldec = Analyze(exp->mLeft->mLeft->mLeft, procDec, 0);
|
||||||
rdec = Analyze(exp->mRight, procDec, false, false);
|
rdec = Analyze(exp->mRight, procDec, 0);
|
||||||
if (exp->mLeft->mLeft->mRight)
|
if (exp->mLeft->mLeft->mRight)
|
||||||
ldec = Analyze(exp->mLeft->mLeft->mRight, procDec, false, false);
|
ldec = Analyze(exp->mLeft->mLeft->mRight, procDec, 0);
|
||||||
|
break;
|
||||||
|
case EX_FORBODY:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||||
|
if (exp->mRight)
|
||||||
|
Analyze(exp->mRight, procDec, 0);
|
||||||
break;
|
break;
|
||||||
case EX_DO:
|
case EX_DO:
|
||||||
procDec->mComplexity += 20;
|
procDec->mComplexity += 20;
|
||||||
|
|
||||||
ldec = Analyze(exp->mLeft, procDec, false, false);
|
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||||
rdec = Analyze(exp->mRight, procDec, false, false);
|
rdec = Analyze(exp->mRight, procDec, 0);
|
||||||
break;
|
break;
|
||||||
case EX_BREAK:
|
case EX_BREAK:
|
||||||
case EX_CONTINUE:
|
case EX_CONTINUE:
|
||||||
|
@ -1143,18 +1161,18 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
||||||
case EX_TYPE:
|
case EX_TYPE:
|
||||||
break;
|
break;
|
||||||
case EX_TYPECAST:
|
case EX_TYPECAST:
|
||||||
return Analyze(exp->mLeft, procDec, false, false);
|
return Analyze(exp->mLeft, procDec, 0);
|
||||||
break;
|
break;
|
||||||
case EX_LOGICAL_AND:
|
case EX_LOGICAL_AND:
|
||||||
ldec = Analyze(exp->mLeft, procDec, false, false);
|
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||||
rdec = Analyze(exp->mRight, procDec, false, false);
|
rdec = Analyze(exp->mRight, procDec, 0);
|
||||||
break;
|
break;
|
||||||
case EX_LOGICAL_OR:
|
case EX_LOGICAL_OR:
|
||||||
ldec = Analyze(exp->mLeft, procDec, false, false);
|
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||||
rdec = Analyze(exp->mRight, procDec, false, false);
|
rdec = Analyze(exp->mRight, procDec, 0);
|
||||||
break;
|
break;
|
||||||
case EX_LOGICAL_NOT:
|
case EX_LOGICAL_NOT:
|
||||||
ldec = Analyze(exp->mLeft, procDec, false, false);
|
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||||
break;
|
break;
|
||||||
case EX_ASSEMBLER:
|
case EX_ASSEMBLER:
|
||||||
procDec->mFlags |= DTF_FUNC_ASSEMBLER;
|
procDec->mFlags |= DTF_FUNC_ASSEMBLER;
|
||||||
|
@ -1165,14 +1183,14 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
||||||
case EX_UNDEFINED:
|
case EX_UNDEFINED:
|
||||||
break;
|
break;
|
||||||
case EX_SWITCH:
|
case EX_SWITCH:
|
||||||
ldec = Analyze(exp->mLeft, procDec, false, false);
|
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||||
exp = exp->mRight;
|
exp = exp->mRight;
|
||||||
while (exp)
|
while (exp)
|
||||||
{
|
{
|
||||||
procDec->mComplexity += 10;
|
procDec->mComplexity += 10;
|
||||||
|
|
||||||
if (exp->mLeft->mRight)
|
if (exp->mLeft->mRight)
|
||||||
rdec = Analyze(exp->mLeft->mRight, procDec, false, false);
|
rdec = Analyze(exp->mLeft->mRight, procDec, 0);
|
||||||
exp = exp->mRight;
|
exp = exp->mRight;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1183,9 +1201,9 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
||||||
case EX_CONDITIONAL:
|
case EX_CONDITIONAL:
|
||||||
procDec->mComplexity += exp->mDecType->mSize * 10;
|
procDec->mComplexity += exp->mDecType->mSize * 10;
|
||||||
|
|
||||||
ldec = Analyze(exp->mLeft, procDec, false, false);
|
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||||
RegisterProc(Analyze(exp->mRight->mLeft, procDec, lhs, aliasing));
|
RegisterProc(Analyze(exp->mRight->mLeft, procDec, flags));
|
||||||
RegisterProc(Analyze(exp->mRight->mRight, procDec, lhs, aliasing));
|
RegisterProc(Analyze(exp->mRight->mRight, procDec, flags));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ protected:
|
||||||
int CallerInvokes(Declaration* called);
|
int CallerInvokes(Declaration* called);
|
||||||
int CallerInvokes(Declaration* caller, Declaration* called);
|
int CallerInvokes(Declaration* caller, Declaration* called);
|
||||||
|
|
||||||
Declaration* Analyze(Expression* exp, Declaration* procDec, bool lhs, bool aliasing);
|
Declaration* Analyze(Expression* exp, Declaration* procDec, uint32 flags);
|
||||||
|
|
||||||
bool IsStackParam(const Declaration* pdec) const;
|
bool IsStackParam(const Declaration* pdec) const;
|
||||||
bool MarkCycle(Declaration* rootDec, Declaration* procDec);
|
bool MarkCycle(Declaration* rootDec, Declaration* procDec);
|
||||||
|
|
|
@ -60,7 +60,7 @@ void GlobalOptimizer::Reset(void)
|
||||||
mFunctions.SetSize(0);
|
mFunctions.SetSize(0);
|
||||||
mGlobalVariables.SetSize(0);
|
mGlobalVariables.SetSize(0);
|
||||||
mCalledFunctions.SetSize(0);
|
mCalledFunctions.SetSize(0);
|
||||||
mCalledFunctions.SetSize(0);
|
mCallingFunctions.SetSize(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlobalOptimizer::PropagateParamCommas(Expression*& fexp, Expression*& exp)
|
void GlobalOptimizer::PropagateParamCommas(Expression*& fexp, Expression*& exp)
|
||||||
|
@ -243,6 +243,19 @@ bool GlobalOptimizer::ReplaceParamConst(Expression* exp, Declaration* param)
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
if (exp)
|
if (exp)
|
||||||
{
|
{
|
||||||
|
if (ReplaceParamConst(exp->mLeft, param))
|
||||||
|
changed = true;
|
||||||
|
if (ReplaceParamConst(exp->mRight, param))
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
if (changed)
|
||||||
|
{
|
||||||
|
if (exp->mLeft)
|
||||||
|
exp->mLeft = exp->mLeft->ConstantFold(mErrors, nullptr);
|
||||||
|
if (exp->mRight)
|
||||||
|
exp->mRight = exp->mRight->ConstantFold(mErrors, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
if (exp->mType == EX_VARIABLE && exp->mDecValue == param)
|
if (exp->mType == EX_VARIABLE && exp->mDecValue == param)
|
||||||
{
|
{
|
||||||
exp->mType = EX_CONSTANT;
|
exp->mType = EX_CONSTANT;
|
||||||
|
@ -251,10 +264,6 @@ bool GlobalOptimizer::ReplaceParamConst(Expression* exp, Declaration* param)
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ReplaceParamConst(exp->mLeft, param))
|
|
||||||
changed = true;
|
|
||||||
if (ReplaceParamConst(exp->mRight, param))
|
|
||||||
changed = true;
|
|
||||||
}
|
}
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
@ -266,15 +275,23 @@ bool GlobalOptimizer::ReplaceGlobalConst(Expression* 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)
|
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;
|
Expression* cexp = exp->mDecValue->mValue;
|
||||||
if (cexp->mType == EX_CONSTANT &&
|
if (cexp->mType == EX_CONSTANT)
|
||||||
(cexp->mDecValue->mType == DT_CONST_ADDRESS || cexp->mDecValue->mType == DT_CONST_INTEGER ||
|
{
|
||||||
cexp->mDecValue->mType == DT_CONST_POINTER || cexp->mDecValue->mType == DT_CONST_FLOAT))
|
|
||||||
|
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->mType = EX_CONSTANT;
|
||||||
exp->mDecValue = cexp->mDecValue->ConstCast(exp->mDecType);
|
exp->mDecValue = cexp->mDecValue->ConstCast(exp->mDecType);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
else if (exp->mDecValue->mBase->mType == DT_TYPE_STRUCT)
|
||||||
|
{
|
||||||
|
exp->mDecValue->mBase = exp->mDecValue->mBase->ToConstType();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ReplaceGlobalConst(exp->mLeft))
|
if (ReplaceGlobalConst(exp->mLeft))
|
||||||
|
@ -324,7 +341,7 @@ bool GlobalOptimizer::Optimize(void)
|
||||||
|
|
||||||
if (!(func->mOptFlags & OPTF_FUNC_VARIABLE) && !(func->mBase->mFlags & DTF_VIRTUAL))
|
if (!(func->mOptFlags & OPTF_FUNC_VARIABLE) && !(func->mBase->mFlags & DTF_VIRTUAL))
|
||||||
{
|
{
|
||||||
if (!(func->mOptFlags & OPTF_VAR_USED) && func->mBase->mBase && (func->mBase->mBase->IsSimpleType() || func->mBase->mBase->IsReference()))
|
if (!(func->mOptFlags & (OPTF_VAR_USED | OPTF_VAR_ADDRESS)) && func->mBase->mBase && (func->mBase->mBase->IsSimpleType() || func->mBase->mBase->IsReference()))
|
||||||
{
|
{
|
||||||
#if DUMP_OPTS
|
#if DUMP_OPTS
|
||||||
printf("Remove return value\n");
|
printf("Remove return value\n");
|
||||||
|
@ -382,6 +399,7 @@ bool GlobalOptimizer::Optimize(void)
|
||||||
{
|
{
|
||||||
if (ReplaceParamConst(func->mValue, pdec))
|
if (ReplaceParamConst(func->mValue, pdec))
|
||||||
{
|
{
|
||||||
|
func->mValue = func->mValue->ConstantFold(mErrors, nullptr);
|
||||||
#if DUMP_OPTS
|
#if DUMP_OPTS
|
||||||
printf("Const parameter %s\n", pdec->mIdent ? pdec->mIdent->mString : "_");
|
printf("Const parameter %s\n", pdec->mIdent ? pdec->mIdent->mString : "_");
|
||||||
#endif
|
#endif
|
||||||
|
@ -444,7 +462,7 @@ void GlobalOptimizer::AnalyzeProcedure(Expression* exp, Declaration* procDec)
|
||||||
Analyze(exp, procDec, false);
|
Analyze(exp, procDec, false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mErrors->Error(procDec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", procDec->mQualIdent);
|
mErrors->Error(procDec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", procDec->FullIdent());
|
||||||
|
|
||||||
procDec->mOptFlags &= ~OPTF_ANALYZING;
|
procDec->mOptFlags &= ~OPTF_ANALYZING;
|
||||||
}
|
}
|
||||||
|
@ -596,9 +614,6 @@ void GlobalOptimizer::RegisterProc(Declaration* to)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint32 ANAFL_LHS = (1U << 0);
|
|
||||||
static const uint32 ANAFL_RHS = (1U << 1);
|
|
||||||
|
|
||||||
Declaration* GlobalOptimizer::Analyze(Expression* exp, Declaration* procDec, uint32 flags)
|
Declaration* GlobalOptimizer::Analyze(Expression* exp, Declaration* procDec, uint32 flags)
|
||||||
{
|
{
|
||||||
Declaration* ldec, * rdec;
|
Declaration* ldec, * rdec;
|
||||||
|
@ -644,6 +659,8 @@ Declaration* GlobalOptimizer::Analyze(Expression* exp, Declaration* procDec, uin
|
||||||
exp->mDecValue->mOptFlags |= OPTF_VAR_USED;
|
exp->mDecValue->mOptFlags |= OPTF_VAR_USED;
|
||||||
if (flags & ANAFL_LHS)
|
if (flags & ANAFL_LHS)
|
||||||
exp->mDecValue->mOptFlags |= OPTF_VAR_ADDRESS;
|
exp->mDecValue->mOptFlags |= OPTF_VAR_ADDRESS;
|
||||||
|
if (exp->mDecValue->mBase->IsReference() && (flags & ANAFL_ASSIGN))
|
||||||
|
exp->mDecValue->mOptFlags |= OPTF_VAR_USED;
|
||||||
|
|
||||||
if (exp->mDecValue->mType == DT_ARGUMENT && (flags & ANAFL_LHS))
|
if (exp->mDecValue->mType == DT_ARGUMENT && (flags & ANAFL_LHS))
|
||||||
{
|
{
|
||||||
|
@ -655,7 +672,12 @@ Declaration* GlobalOptimizer::Analyze(Expression* exp, Declaration* procDec, uin
|
||||||
case EX_INITIALIZATION:
|
case EX_INITIALIZATION:
|
||||||
case EX_ASSIGNMENT:
|
case EX_ASSIGNMENT:
|
||||||
if (exp->mToken == TK_ASSIGN)
|
if (exp->mToken == TK_ASSIGN)
|
||||||
|
{
|
||||||
|
if (exp->mType == EX_ASSIGNMENT)
|
||||||
|
ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_ASSIGN | flags);
|
||||||
|
else
|
||||||
ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | flags);
|
ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | flags);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_RHS | flags);
|
ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_RHS | flags);
|
||||||
|
|
||||||
|
@ -803,6 +825,22 @@ Declaration* GlobalOptimizer::Analyze(Expression* exp, Declaration* procDec, uin
|
||||||
pdec->mOptFlags |= OPTF_VAR_CONST;
|
pdec->mOptFlags |= OPTF_VAR_CONST;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (pex->mType == EX_VARIABLE && pdec->mBase->mType == DT_TYPE_POINTER && pex->mDecType->mType == DT_TYPE_ARRAY && (pex->mDecValue->mFlags & (DTF_GLOBAL | DTF_STATIC)) && pdec->mBase->CanAssign(pex->mDecType))
|
||||||
|
{
|
||||||
|
if (pdec->mOptFlags & OPTF_VAR_CONST)
|
||||||
|
{
|
||||||
|
if (pdec->mValue->mType != EX_VARIABLE || pdec->mValue->mDecValue != pex->mDecValue)
|
||||||
|
{
|
||||||
|
pdec->mOptFlags |= OPTF_VAR_NOCONST;
|
||||||
|
pdec->mOptFlags &= ~OPTF_VAR_CONST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pdec->mValue = pex;
|
||||||
|
pdec->mOptFlags |= OPTF_VAR_CONST;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pdec->mOptFlags |= OPTF_VAR_NOCONST;
|
pdec->mOptFlags |= OPTF_VAR_NOCONST;
|
||||||
|
@ -948,13 +986,20 @@ Declaration* GlobalOptimizer::Analyze(Expression* exp, Declaration* procDec, uin
|
||||||
if (exp->mLeft->mLeft->mRight)
|
if (exp->mLeft->mLeft->mRight)
|
||||||
ldec = Analyze(exp->mLeft->mLeft->mRight, procDec, 0);
|
ldec = Analyze(exp->mLeft->mLeft->mRight, procDec, 0);
|
||||||
break;
|
break;
|
||||||
|
case EX_FORBODY:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||||
|
if (exp->mRight)
|
||||||
|
rdec = Analyze(exp->mRight, procDec, 0);
|
||||||
|
break;
|
||||||
case EX_DO:
|
case EX_DO:
|
||||||
ldec = Analyze(exp->mRight, procDec, 0);
|
ldec = Analyze(exp->mRight, procDec, 0);
|
||||||
rdec = Analyze(exp->mLeft, procDec, ANAFL_RHS);
|
rdec = Analyze(exp->mLeft, procDec, ANAFL_RHS);
|
||||||
break;
|
break;
|
||||||
case EX_BREAK:
|
case EX_BREAK:
|
||||||
case EX_CONTINUE:
|
case EX_CONTINUE:
|
||||||
|
break;
|
||||||
case EX_ASSUME:
|
case EX_ASSUME:
|
||||||
|
return Analyze(exp->mLeft, procDec, ANAFL_RHS);
|
||||||
break;
|
break;
|
||||||
case EX_TYPE:
|
case EX_TYPE:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -47,7 +47,7 @@ const Ident* Ident::Unique(const char* str)
|
||||||
|
|
||||||
const Ident* Ident::PreMangle(const char* str) const
|
const Ident* Ident::PreMangle(const char* str) const
|
||||||
{
|
{
|
||||||
char buffer[200];
|
char buffer[1000];
|
||||||
strcpy_s(buffer, str);
|
strcpy_s(buffer, str);
|
||||||
strcat_s(buffer, mString);
|
strcat_s(buffer, mString);
|
||||||
return Unique(buffer);
|
return Unique(buffer);
|
||||||
|
@ -55,14 +55,14 @@ const Ident* Ident::PreMangle(const char* str) const
|
||||||
|
|
||||||
const Ident* Ident::Unique(const char* str, int id)
|
const Ident* Ident::Unique(const char* str, int id)
|
||||||
{
|
{
|
||||||
char buffer[200];
|
char buffer[1000];
|
||||||
sprintf_s(buffer, "%s#%d", str, id);
|
sprintf_s(buffer, "%s#%d", str, id);
|
||||||
return Unique(buffer);
|
return Unique(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Ident* Ident::Mangle(const char* str) const
|
const Ident* Ident::Mangle(const char* str) const
|
||||||
{
|
{
|
||||||
char buffer[200];
|
char buffer[1000];
|
||||||
strcpy_s(buffer, mString);
|
strcpy_s(buffer, mString);
|
||||||
strcat_s(buffer, str);
|
strcat_s(buffer, str);
|
||||||
return Unique(buffer);
|
return Unique(buffer);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -169,6 +169,7 @@ public:
|
||||||
} mMinState, mMaxState;
|
} mMinState, mMaxState;
|
||||||
|
|
||||||
bool Same(const IntegerValueRange& range) const;
|
bool Same(const IntegerValueRange& range) const;
|
||||||
|
bool Weaker(const IntegerValueRange& range) const;
|
||||||
bool Merge(const IntegerValueRange& range, bool head, bool initial);
|
bool Merge(const IntegerValueRange& range, bool head, bool initial);
|
||||||
void Expand(const IntegerValueRange& range);
|
void Expand(const IntegerValueRange& range);
|
||||||
void Union(const IntegerValueRange& range);
|
void Union(const IntegerValueRange& range);
|
||||||
|
@ -198,7 +199,7 @@ public:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef GrowingArray<IntegerValueRange> GrowingIntegerValueRangeArray;
|
typedef ExpandingArray<IntegerValueRange> GrowingIntegerValueRangeArray;
|
||||||
|
|
||||||
class ValueSet
|
class ValueSet
|
||||||
{
|
{
|
||||||
|
@ -380,7 +381,7 @@ public:
|
||||||
InterCodeBasicBlock * mTrueJump, * mFalseJump, * mLoopPrefix, * mDominator;
|
InterCodeBasicBlock * mTrueJump, * mFalseJump, * mLoopPrefix, * mDominator;
|
||||||
GrowingInstructionArray mInstructions;
|
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;
|
mutable int mMark;
|
||||||
|
|
||||||
NumberSet mLocalUsedTemps, mLocalModifiedTemps;
|
NumberSet mLocalUsedTemps, mLocalModifiedTemps;
|
||||||
|
@ -423,14 +424,15 @@ public:
|
||||||
InterCodeBasicBlock* Clone(void);
|
InterCodeBasicBlock* Clone(void);
|
||||||
|
|
||||||
void Append(InterInstruction * code);
|
void Append(InterInstruction * code);
|
||||||
void AppendBeforeBranch(InterInstruction* code);
|
void AppendBeforeBranch(InterInstruction* code, bool loopindex = false);
|
||||||
const InterInstruction* FindByDst(int dst) const;
|
const InterInstruction* FindByDst(int dst) const;
|
||||||
void Close(InterCodeBasicBlock* trueJump, InterCodeBasicBlock* falseJump);
|
void Close(InterCodeBasicBlock* trueJump, InterCodeBasicBlock* falseJump);
|
||||||
|
|
||||||
void CollectEntries(void);
|
void CollectEntries(void);
|
||||||
void CollectEntryBlocks(InterCodeBasicBlock* from);
|
void CollectEntryBlocks(InterCodeBasicBlock* from);
|
||||||
void GenerateTraces(bool expand, bool compact);
|
void GenerateTraces(int expand, bool compact);
|
||||||
void BuildDominatorTree(InterCodeBasicBlock * from);
|
void BuildDominatorTree(InterCodeBasicBlock * from);
|
||||||
|
bool StripLoopHead(void);
|
||||||
|
|
||||||
bool MergeSameConditionTraces(void);
|
bool MergeSameConditionTraces(void);
|
||||||
|
|
||||||
|
@ -448,6 +450,7 @@ public:
|
||||||
void CollectConstTemps(GrowingInstructionPtrArray& ctemps, NumberSet& assignedTemps);
|
void CollectConstTemps(GrowingInstructionPtrArray& ctemps, NumberSet& assignedTemps);
|
||||||
bool PropagateConstTemps(const GrowingInstructionPtrArray& ctemps);
|
bool PropagateConstTemps(const GrowingInstructionPtrArray& ctemps);
|
||||||
bool ForwardConstTemps(const GrowingInstructionPtrArray& ctemps);
|
bool ForwardConstTemps(const GrowingInstructionPtrArray& ctemps);
|
||||||
|
bool PropagateConstCompareResults(void);
|
||||||
|
|
||||||
bool EarlyBranchElimination(const GrowingInstructionPtrArray& ctemps);
|
bool EarlyBranchElimination(const GrowingInstructionPtrArray& ctemps);
|
||||||
|
|
||||||
|
@ -480,6 +483,8 @@ public:
|
||||||
|
|
||||||
bool CheckSingleBlockLimitedLoop(InterCodeBasicBlock*& pblock, int64 & nloop);
|
bool CheckSingleBlockLimitedLoop(InterCodeBasicBlock*& pblock, int64 & nloop);
|
||||||
|
|
||||||
|
bool TempIsUnsigned(int temp);
|
||||||
|
|
||||||
void RestartLocalIntegerRangeSets(int num, const GrowingVariableArray& localVars, const GrowingVariableArray& paramVars);
|
void RestartLocalIntegerRangeSets(int num, const GrowingVariableArray& localVars, const GrowingVariableArray& paramVars);
|
||||||
void BuildLocalIntegerRangeSets(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 UpdateLocalIntegerRangeSets(const GrowingVariableArray& localVars, const GrowingVariableArray& paramVars);
|
||||||
|
@ -515,6 +520,8 @@ public:
|
||||||
void PerformMachineSpecificValueUsageCheck(const GrowingInstructionPtrArray& tvalue, FastNumberSet& tvalid, const GrowingVariableArray& staticVars, const GrowingInterCodeProcedurePtrArray& staticProcs, FastNumberSet& fsingle);
|
void PerformMachineSpecificValueUsageCheck(const GrowingInstructionPtrArray& tvalue, FastNumberSet& tvalid, const GrowingVariableArray& staticVars, const GrowingInterCodeProcedurePtrArray& staticProcs, FastNumberSet& fsingle);
|
||||||
bool EliminateDeadBranches(void);
|
bool EliminateDeadBranches(void);
|
||||||
|
|
||||||
|
bool EliminateIntegerSumAliasTemps(const GrowingInstructionPtrArray& tvalue);
|
||||||
|
|
||||||
bool MergeIndexedLoadStore(const GrowingInstructionPtrArray& tvalue);
|
bool MergeIndexedLoadStore(const GrowingInstructionPtrArray& tvalue);
|
||||||
bool SimplifyIntegerNumeric(const GrowingInstructionPtrArray& tvalue, int& spareTemps);
|
bool SimplifyIntegerNumeric(const GrowingInstructionPtrArray& tvalue, int& spareTemps);
|
||||||
bool SimplifyPointerOffsets(void);
|
bool SimplifyPointerOffsets(void);
|
||||||
|
@ -623,29 +630,42 @@ public:
|
||||||
void SingleBlockLoopUnrolling(void);
|
void SingleBlockLoopUnrolling(void);
|
||||||
bool SingleBlockLoopPointerSplit(int& spareTemps);
|
bool SingleBlockLoopPointerSplit(int& spareTemps);
|
||||||
bool SingleBlockLoopPointerToByte(int& spareTemps);
|
bool SingleBlockLoopPointerToByte(int& spareTemps);
|
||||||
|
bool SingleBlockLoopSinking(int& spareTemps);
|
||||||
bool CollectLoopBody(InterCodeBasicBlock* head, ExpandingArray<InterCodeBasicBlock*> & body);
|
bool CollectLoopBody(InterCodeBasicBlock* head, ExpandingArray<InterCodeBasicBlock*> & body);
|
||||||
bool CollectLoopBodyRecursive(InterCodeBasicBlock* head, ExpandingArray<InterCodeBasicBlock*>& body);
|
bool CollectLoopBodyRecursive(InterCodeBasicBlock* head, ExpandingArray<InterCodeBasicBlock*>& body);
|
||||||
void CollectLoopPath(const ExpandingArray<InterCodeBasicBlock*>& body, ExpandingArray<InterCodeBasicBlock*>& path);
|
void CollectLoopPath(const ExpandingArray<InterCodeBasicBlock*>& body, ExpandingArray<InterCodeBasicBlock*>& path);
|
||||||
void InnerLoopOptimization(const NumberSet& aliasedParams);
|
void InnerLoopOptimization(const NumberSet& aliasedParams);
|
||||||
void ConstLoopOptimization(void);
|
void ConstLoopOptimization(void);
|
||||||
|
bool EmptyLoopOptimization(void);
|
||||||
void EliminateDoubleLoopCounter(void);
|
void EliminateDoubleLoopCounter(void);
|
||||||
void PushMoveOutOfLoop(void);
|
void PushMoveOutOfLoop(void);
|
||||||
bool MoveConditionOutOfLoop(void);
|
bool MoveConditionOutOfLoop(void);
|
||||||
void SingleLoopCountZeroCheck(void);
|
void SingleLoopCountZeroCheck(void);
|
||||||
|
void InnerLoopCountZeroCheck(void);
|
||||||
bool PostDecLoopOptimization(void);
|
bool PostDecLoopOptimization(void);
|
||||||
|
bool Flatten2DLoop(void);
|
||||||
|
|
||||||
void PropagateMemoryAliasingInfo(const GrowingInstructionPtrArray& tvalue);
|
void PropagateMemoryAliasingInfo(const GrowingInstructionPtrArray& tvalue, bool loops);
|
||||||
void RemoveUnusedMallocs(void);
|
void RemoveUnusedMallocs(void);
|
||||||
|
|
||||||
bool PullStoreUpToConstAddress(void);
|
bool PullStoreUpToConstAddress(void);
|
||||||
|
|
||||||
bool CollectSingleHeadLoopBody(InterCodeBasicBlock* head, InterCodeBasicBlock* tail, GrowingArray<InterCodeBasicBlock*>& body);
|
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 SingleTailLoopOptimization(const NumberSet& aliasedParams, const GrowingVariableArray& staticVars);
|
||||||
bool MergeLoopTails(void);
|
bool MergeLoopTails(void);
|
||||||
|
|
||||||
|
bool ChangeTrueJump(InterCodeBasicBlock* block);
|
||||||
|
bool ChangeFalseJump(InterCodeBasicBlock* block);
|
||||||
|
|
||||||
|
InterCodeBasicBlock* CheckIsSimpleIntRangeBranch(const GrowingIntegerValueRangeArray & irange);
|
||||||
InterCodeBasicBlock* CheckIsConstBranch(const GrowingInstructionPtrArray& cins);
|
InterCodeBasicBlock* CheckIsConstBranch(const GrowingInstructionPtrArray& cins);
|
||||||
bool ShortcutConstBranches(const GrowingInstructionPtrArray& cins);
|
bool ShortcutConstBranches(const GrowingInstructionPtrArray& cins);
|
||||||
|
bool ShortcutDuplicateBranches(void);
|
||||||
|
|
||||||
InterCodeBasicBlock* BuildLoopPrefix(void);
|
InterCodeBasicBlock* BuildLoopPrefix(void);
|
||||||
void BuildLoopSuffix(void);
|
void BuildLoopSuffix(void);
|
||||||
|
@ -656,6 +676,7 @@ public:
|
||||||
void FollowJumps(void);
|
void FollowJumps(void);
|
||||||
|
|
||||||
bool ShortLeaMerge(int& spareTemps);
|
bool ShortLeaMerge(int& spareTemps);
|
||||||
|
bool ShortLeaCleanup(void);
|
||||||
|
|
||||||
bool IsEqual(const InterCodeBasicBlock* block) const;
|
bool IsEqual(const InterCodeBasicBlock* block) const;
|
||||||
|
|
||||||
|
@ -692,6 +713,7 @@ protected:
|
||||||
GrowingIntegerValueRangeArray mLocalValueRange, mReverseValueRange;
|
GrowingIntegerValueRangeArray mLocalValueRange, mReverseValueRange;
|
||||||
|
|
||||||
void ResetVisited(void);
|
void ResetVisited(void);
|
||||||
|
void ResetPatched(void);
|
||||||
void ResetEntryBlocks(void);
|
void ResetEntryBlocks(void);
|
||||||
public:
|
public:
|
||||||
InterCodeBasicBlock * mEntryBlock;
|
InterCodeBasicBlock * mEntryBlock;
|
||||||
|
@ -753,7 +775,7 @@ public:
|
||||||
void Disassemble(const char* name, bool dumpSets = false);
|
void Disassemble(const char* name, bool dumpSets = false);
|
||||||
protected:
|
protected:
|
||||||
void BuildLocalAliasTable(void);
|
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 TrimBlocks(void);
|
||||||
void EarlyBranchElimination(void);
|
void EarlyBranchElimination(void);
|
||||||
void BuildDataFlowSets(void);
|
void BuildDataFlowSets(void);
|
||||||
|
@ -774,7 +796,9 @@ protected:
|
||||||
void SimplifyIntegerNumeric(FastNumberSet& activeSet);
|
void SimplifyIntegerNumeric(FastNumberSet& activeSet);
|
||||||
void SingleBlockLoopPointerSplit(FastNumberSet& activeSet);
|
void SingleBlockLoopPointerSplit(FastNumberSet& activeSet);
|
||||||
void SingleBlockLoopPointerToByte(FastNumberSet& activeSet);
|
void SingleBlockLoopPointerToByte(FastNumberSet& activeSet);
|
||||||
|
void SingleBlockLoopSinking(FastNumberSet& activeSet);
|
||||||
void MergeIndexedLoadStore(void);
|
void MergeIndexedLoadStore(void);
|
||||||
|
void EliminateIntegerSumAliasTemps(void);
|
||||||
void EliminateAliasValues();
|
void EliminateAliasValues();
|
||||||
void LoadStoreForwarding(InterMemory paramMemory);
|
void LoadStoreForwarding(InterMemory paramMemory);
|
||||||
void ReduceRecursionTempSpilling(InterMemory paramMemory);
|
void ReduceRecursionTempSpilling(InterMemory paramMemory);
|
||||||
|
@ -794,9 +818,10 @@ protected:
|
||||||
void CheckUsedDefinedTemps(void);
|
void CheckUsedDefinedTemps(void);
|
||||||
void WarnUsedUndefinedVariables(void);
|
void WarnUsedUndefinedVariables(void);
|
||||||
void WarnInvalidValueRanges(void);
|
void WarnInvalidValueRanges(void);
|
||||||
void PropagateMemoryAliasingInfo(void);
|
void PropagateMemoryAliasingInfo(bool loops);
|
||||||
void MoveConditionsOutOfLoop(void);
|
void MoveConditionsOutOfLoop(void);
|
||||||
void ShortcutConstBranches(void);
|
void ShortcutConstBranches(void);
|
||||||
|
void ShortcutDuplicateBranches(void);
|
||||||
void EliminateDoubleLoopCounter(void);
|
void EliminateDoubleLoopCounter(void);
|
||||||
void StructReturnPropagation(void);
|
void StructReturnPropagation(void);
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -45,7 +45,7 @@ public:
|
||||||
uint64 mCompilerOptions;
|
uint64 mCompilerOptions;
|
||||||
|
|
||||||
InterCodeProcedure* TranslateProcedure(InterCodeModule* mod, Expression* exp, Declaration * dec);
|
InterCodeProcedure* TranslateProcedure(InterCodeModule* mod, Expression* exp, Declaration * dec);
|
||||||
void TranslateAssembler(InterCodeModule* mod, Expression * exp, GrowingArray<Declaration *> * refvars);
|
void TranslateAssembler(InterCodeModule* mod, Declaration* adec,GrowingArray<Declaration *> * refvars);
|
||||||
void InitGlobalVariable(InterCodeModule* mod, Declaration* dec);
|
void InitGlobalVariable(InterCodeModule* mod, Declaration* dec);
|
||||||
void InitLocalVariable(InterCodeProcedure* proc, Declaration* dec, int index);
|
void InitLocalVariable(InterCodeProcedure* proc, Declaration* dec, int index);
|
||||||
void InitParameter(InterCodeProcedure* proc, Declaration* dec, int index);
|
void InitParameter(InterCodeProcedure* proc, Declaration* dec, int index);
|
||||||
|
@ -94,12 +94,12 @@ protected:
|
||||||
void BuildSwitchTree(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock* block, InlineMapper * inlineMapper, ExValue v, const SwitchNodeArray& nodes, int left, int right, int vleft, int vright, InterCodeBasicBlock* dblock);
|
void BuildSwitchTree(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock* block, InlineMapper * inlineMapper, ExValue v, const SwitchNodeArray& nodes, int left, int right, int vleft, int vright, InterCodeBasicBlock* dblock);
|
||||||
|
|
||||||
ExValue ToValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, InlineMapper* inlineMapper, ExValue v);
|
ExValue ToValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, InlineMapper* inlineMapper, ExValue v);
|
||||||
ExValue Dereference(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, InlineMapper* inlineMapper, ExValue v, int level = 0);
|
ExValue Dereference(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, InlineMapper* inlineMapper, ExValue v, int level = 0, int limit = 0);
|
||||||
ExValue CoerceType(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, InlineMapper* inlineMapper, ExValue v, Declaration * type, bool checkTrunc = true);
|
ExValue CoerceType(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, InlineMapper* inlineMapper, ExValue v, Declaration * type, bool checkTrunc = true);
|
||||||
ExValue TranslateExpression(Declaration * procType, InterCodeProcedure * proc, InterCodeBasicBlock*& block, Expression* exp, DestructStack*& destack, GotoNode*& gotos, const BranchTarget & breakBlock, const BranchTarget& continueBlock, InlineMapper * inlineMapper, ExValue * lrexp = nullptr);
|
ExValue TranslateExpression(Declaration * procType, InterCodeProcedure * proc, InterCodeBasicBlock*& block, Expression* exp, DestructStack*& destack, GotoNode*& gotos, const BranchTarget & breakBlock, const BranchTarget& continueBlock, InlineMapper * inlineMapper, ExValue * lrexp = nullptr);
|
||||||
void TranslateLogic(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock* block, InterCodeBasicBlock* tblock, InterCodeBasicBlock* fblock, Expression* exp, DestructStack*& destack, GotoNode*& gotos, InlineMapper* inlineMapper);
|
void TranslateLogic(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock* block, InterCodeBasicBlock* tblock, InterCodeBasicBlock* fblock, Expression* exp, DestructStack*& destack, GotoNode*& gotos, InlineMapper* inlineMapper);
|
||||||
ExValue TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr, ExValue* lrexp);
|
ExValue TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr, ExValue* lrexp);
|
||||||
void CopyStruct(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr, InlineMapper* inlineMapper, bool moving);
|
void CopyStruct (InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr, InlineMapper* inlineMapper, bool moving);
|
||||||
void CopyStructSimple(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock * block, InlineMapper* inlineMapper, ExValue vl, ExValue vr);
|
void CopyStructSimple(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock * block, InlineMapper* inlineMapper, ExValue vl, ExValue vr);
|
||||||
void StoreValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, InlineMapper* inlineMapper, ExValue vl, ExValue vr);
|
void StoreValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, InlineMapper* inlineMapper, ExValue vl, ExValue vr);
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ bool LinkerReference::operator!=(const LinkerReference& ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
LinkerObject::LinkerObject(void)
|
LinkerObject::LinkerObject(void)
|
||||||
: mReferences(nullptr), mNumTemporaries(0), mSize(0), mAlignment(1), mStackSection(nullptr), mIdent(nullptr), mFullIdent(nullptr), mStartUsed(0x10000), mEndUsed(0x00000), mMemory(nullptr)
|
: mReferences(nullptr), mNumTemporaries(0), mSize(0), mStripe(0), mAlignment(1), mStackSection(nullptr), mIdent(nullptr), mFullIdent(nullptr), mStartUsed(0x10000), mEndUsed(0x00000), mMemory(nullptr)
|
||||||
, mPrefix(nullptr), mSuffix(nullptr), mProc(nullptr), mNativeProc(nullptr)
|
, mPrefix(nullptr), mSuffix(nullptr), mProc(nullptr), mNativeProc(nullptr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -54,6 +54,23 @@ LinkerObject::~LinkerObject(void)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LinkerObject* LinkerObject::CloneAssembler(Linker* linker) const
|
||||||
|
{
|
||||||
|
LinkerObject* lo = linker->AddObject(mLocation, mIdent, mSection, mType, mAlignment);
|
||||||
|
lo->AddData(mData, mSize);
|
||||||
|
lo->mFlags = mFlags;
|
||||||
|
|
||||||
|
for (int i = 0; i < mReferences.Size(); i++)
|
||||||
|
{
|
||||||
|
LinkerReference ref = *(mReferences[i]);
|
||||||
|
if (ref.mObject == this) ref.mObject = lo;
|
||||||
|
if (ref.mRefObject == this) ref.mRefObject = lo;
|
||||||
|
lo->AddReference(ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lo;
|
||||||
|
}
|
||||||
|
|
||||||
void LinkerObject::AddReference(const LinkerReference& ref)
|
void LinkerObject::AddReference(const LinkerReference& ref)
|
||||||
{
|
{
|
||||||
LinkerReference* nref = new LinkerReference(ref);
|
LinkerReference* nref = new LinkerReference(ref);
|
||||||
|
@ -633,7 +650,7 @@ bool LinkerRegion::Allocate(Linker * linker, LinkerObject* lobj, bool merge, boo
|
||||||
int start = (mFreeChunks[i].mStart + lobj->mAlignment - 1) & ~(lobj->mAlignment - 1);
|
int start = (mFreeChunks[i].mStart + lobj->mAlignment - 1) & ~(lobj->mAlignment - 1);
|
||||||
int end = start + lobj->mSize;
|
int end = start + lobj->mSize;
|
||||||
|
|
||||||
if (!(linker->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE) && (lobj->mFlags & LOBJF_NO_CROSS) && lobj->mSize <= 256 && (start & 0xff00) != ((end - 1) & 0xff00) && !(lobj->mSection->mFlags & LSECF_PACKED))
|
if (((lobj->mFlags & LOBJF_NEVER_CROSS) || !(linker->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE) && (lobj->mFlags & LOBJF_NO_CROSS) && !(lobj->mSection->mFlags & LSECF_PACKED)) && lobj->mSize <= 256 && (start & 0xff00) != ((end - 1) & 0xff00))
|
||||||
;
|
;
|
||||||
else if (end <= mFreeChunks[i].mEnd)
|
else if (end <= mFreeChunks[i].mEnd)
|
||||||
{
|
{
|
||||||
|
@ -685,7 +702,7 @@ bool LinkerRegion::Allocate(Linker * linker, LinkerObject* lobj, bool merge, boo
|
||||||
int start = (mStart + mUsed + lobj->mAlignment - 1) & ~(lobj->mAlignment - 1);
|
int start = (mStart + mUsed + lobj->mAlignment - 1) & ~(lobj->mAlignment - 1);
|
||||||
int end = start + lobj->mSize;
|
int end = start + lobj->mSize;
|
||||||
|
|
||||||
if (!(linker->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE) && !retry && (lobj->mFlags & LOBJF_NO_CROSS) && !(lobj->mFlags & LOBJF_FORCE_ALIGN) && lobj->mSize <= 256 && (start & 0xff00) != ((end - 1) & 0xff00) && !(lobj->mSection->mFlags & LSECF_PACKED))
|
if (((lobj->mFlags & LOBJF_NEVER_CROSS) || !(linker->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE) && !retry && (lobj->mFlags & LOBJF_NO_CROSS) && !(lobj->mSection->mFlags & LSECF_PACKED)) && !(lobj->mFlags & LOBJF_FORCE_ALIGN) && lobj->mSize <= 256 && (start & 0xff00) != ((end - 1) & 0xff00))
|
||||||
{
|
{
|
||||||
start = (start + 0x00ff) & 0xff00;
|
start = (start + 0x00ff) & 0xff00;
|
||||||
end = start + lobj->mSize;
|
end = start + lobj->mSize;
|
||||||
|
@ -1886,6 +1903,8 @@ bool Linker::WriteDbjFile(FILE* file)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char hexchars[] = "0123456789abcdef";
|
||||||
|
|
||||||
bool Linker::WriteLblFile(const char* filename)
|
bool Linker::WriteLblFile(const char* filename)
|
||||||
{
|
{
|
||||||
FILE* file;
|
FILE* file;
|
||||||
|
@ -1899,7 +1918,28 @@ bool Linker::WriteLblFile(const char* filename)
|
||||||
if (obj->mFlags & LOBJF_REFERENCED)
|
if (obj->mFlags & LOBJF_REFERENCED)
|
||||||
{
|
{
|
||||||
if (obj->mIdent)
|
if (obj->mIdent)
|
||||||
fprintf(file, "al %04x .%s\n", obj->mAddress, obj->mIdent->mString);
|
{
|
||||||
|
char buffer[400];
|
||||||
|
char nbuffer[500];
|
||||||
|
|
||||||
|
strcpy_s(buffer, obj->mIdent->mString);
|
||||||
|
int i = 0, j = 0;
|
||||||
|
while (buffer[i])
|
||||||
|
{
|
||||||
|
if (buffer[i] >= '0' && buffer[i] <= '9' || buffer[i] >= 'a' && buffer[i] <= 'z' || buffer[i] >= 'A' && buffer[i] <= 'Z' || buffer[i] == '_' || buffer[i] == ':')
|
||||||
|
nbuffer[j++] = buffer[i];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nbuffer[j++] = '?';
|
||||||
|
nbuffer[j++] = hexchars[(buffer[i] >> 4) & 0x0f];
|
||||||
|
nbuffer[j++] = hexchars[buffer[i] & 0x0f];
|
||||||
|
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
nbuffer[j] = 0;
|
||||||
|
fprintf(file, "al %04x .%s\n", obj->mAddress, nbuffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -156,6 +156,7 @@ static const uint32 LOBJF_NO_CROSS = 0x00000080;
|
||||||
static const uint32 LOBJF_ZEROPAGE = 0x00000100;
|
static const uint32 LOBJF_ZEROPAGE = 0x00000100;
|
||||||
static const uint32 LOBJF_FORCE_ALIGN = 0x00000200;
|
static const uint32 LOBJF_FORCE_ALIGN = 0x00000200;
|
||||||
static const uint32 LOBJF_ZEROPAGESET = 0x00000400;
|
static const uint32 LOBJF_ZEROPAGESET = 0x00000400;
|
||||||
|
static const uint32 LOBJF_NEVER_CROSS = 0x00000800;
|
||||||
|
|
||||||
static const uint32 LOBJF_ARG_REG_A = 0x00001000;
|
static const uint32 LOBJF_ARG_REG_A = 0x00001000;
|
||||||
static const uint32 LOBJF_ARG_REG_X = 0x00002000;
|
static const uint32 LOBJF_ARG_REG_X = 0x00002000;
|
||||||
|
@ -163,6 +164,7 @@ static const uint32 LOBJF_ARG_REG_Y = 0x00004000;
|
||||||
|
|
||||||
static const uint32 LOBJF_RET_REG_A = 0x00010000;
|
static const uint32 LOBJF_RET_REG_A = 0x00010000;
|
||||||
static const uint32 LOBJF_RET_REG_X = 0x00020000;
|
static const uint32 LOBJF_RET_REG_X = 0x00020000;
|
||||||
|
static const uint32 LOBJF_RET_REG_Y = 0x00020000;
|
||||||
|
|
||||||
static const uint32 LOBJF_LOCAL_VAR = 0x00100000;
|
static const uint32 LOBJF_LOCAL_VAR = 0x00100000;
|
||||||
static const uint32 LOBJF_LOCAL_USED = 0x00200000;
|
static const uint32 LOBJF_LOCAL_USED = 0x00200000;
|
||||||
|
@ -190,7 +192,7 @@ public:
|
||||||
LinkerObjectType mType;
|
LinkerObjectType mType;
|
||||||
int mID, mMapID;
|
int mID, mMapID;
|
||||||
int mAddress, mRefAddress;
|
int mAddress, mRefAddress;
|
||||||
int mSize, mAlignment, mStartUsed, mEndUsed;
|
int mSize, mAlignment, mStripe, mStartUsed, mEndUsed;
|
||||||
LinkerSection * mSection;
|
LinkerSection * mSection;
|
||||||
LinkerRegion * mRegion;
|
LinkerRegion * mRegion;
|
||||||
uint8 * mData, * mMemory;
|
uint8 * mData, * mMemory;
|
||||||
|
@ -212,6 +214,8 @@ public:
|
||||||
LinkerObject(void);
|
LinkerObject(void);
|
||||||
~LinkerObject(void);
|
~LinkerObject(void);
|
||||||
|
|
||||||
|
LinkerObject* CloneAssembler(Linker * linker) const;
|
||||||
|
|
||||||
void AddData(const uint8* data, int size);
|
void AddData(const uint8* data, int size);
|
||||||
void AddLocations(const ExpandingArray<CodeLocation>& locations);
|
void AddLocations(const ExpandingArray<CodeLocation>& locations);
|
||||||
uint8* AddSpace(int size);
|
uint8* AddSpace(int size);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -9,6 +9,9 @@ class NativeCodeBasicBlock;
|
||||||
class NativeCodeGenerator;
|
class NativeCodeGenerator;
|
||||||
class NativeCodeInstruction;
|
class NativeCodeInstruction;
|
||||||
|
|
||||||
|
class NativeCodeMapper;
|
||||||
|
class SuffixTree;
|
||||||
|
|
||||||
enum NativeRegisterDataMode
|
enum NativeRegisterDataMode
|
||||||
{
|
{
|
||||||
NRDM_UNKNOWN,
|
NRDM_UNKNOWN,
|
||||||
|
@ -130,19 +133,25 @@ static const uint32 NCIF_ALIASING = 0x00000800;
|
||||||
static const uint32 NCIF_USE_CPU_REG_A = 0x00001000;
|
static const uint32 NCIF_USE_CPU_REG_A = 0x00001000;
|
||||||
static const uint32 NCIF_USE_CPU_REG_X = 0x00002000;
|
static const uint32 NCIF_USE_CPU_REG_X = 0x00002000;
|
||||||
static const uint32 NCIF_USE_CPU_REG_Y = 0x00004000;
|
static const uint32 NCIF_USE_CPU_REG_Y = 0x00004000;
|
||||||
|
static const uint32 NCIF_USE_CPU_REG_C = 0x00008000;
|
||||||
|
|
||||||
|
static const uint32 NCIF_PROVIDE_CPU_REG_A = 0x00010000;
|
||||||
|
static const uint32 NCIF_PROVIDE_CPU_REG_X = 0x00020000;
|
||||||
|
static const uint32 NCIF_PROVIDE_CPU_REG_Y = 0x00040000;
|
||||||
|
static const uint32 NCIF_PROVIDE_CPU_REG_C = 0x00080000;
|
||||||
|
|
||||||
// use a 32bit zero page register indexed by X for JSR
|
// use a 32bit zero page register indexed by X for JSR
|
||||||
static const uint32 NCIF_USE_ZP_32_X = 0x00008000;
|
static const uint32 NCIF_USE_ZP_32_X = 0x00100000;
|
||||||
static const uint32 NICF_USE_ZP_ADDR = 0x00010000;
|
static const uint32 NICF_USE_ZP_ADDR = 0x00200000;
|
||||||
static const uint32 NICF_USE_WORKREGS = 0x00020000;
|
static const uint32 NICF_USE_WORKREGS = 0x00400000;
|
||||||
|
|
||||||
static const uint32 NCIF_BREAKPOINT = 0x00040000;
|
static const uint32 NCIF_BREAKPOINT = 0x00800000;
|
||||||
|
|
||||||
class NativeCodeInstruction
|
class NativeCodeInstruction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NativeCodeInstruction(void);
|
NativeCodeInstruction(void);
|
||||||
NativeCodeInstruction(const InterInstruction * ins, AsmInsType type, AsmInsMode mode = ASMIM_IMPLIED, int64 address = 0, LinkerObject * linkerObject = nullptr, uint32 flags = NCIF_LOWER | NCIF_UPPER, int param = 0);
|
NativeCodeInstruction(const InterInstruction * ins, AsmInsType type, AsmInsMode mode = ASMIM_IMPLIED, int64 address = 0, LinkerObject * linkerObject = nullptr, uint32 flags = NCIF_LOWER | NCIF_UPPER, int param = 0, int minv = 0, int maxv = 255);
|
||||||
NativeCodeInstruction(const InterInstruction* ins, AsmInsType type, const NativeCodeInstruction & addr);
|
NativeCodeInstruction(const InterInstruction* ins, AsmInsType type, const NativeCodeInstruction & addr);
|
||||||
|
|
||||||
AsmInsType mType;
|
AsmInsType mType;
|
||||||
|
@ -153,8 +162,13 @@ public:
|
||||||
uint32 mLive;
|
uint32 mLive;
|
||||||
LinkerObject * mLinkerObject;
|
LinkerObject * mLinkerObject;
|
||||||
const InterInstruction * mIns;
|
const InterInstruction * mIns;
|
||||||
|
uint8 mMinVal, mMaxVal;
|
||||||
|
|
||||||
|
void Disassemble(FILE* file) const;
|
||||||
|
void DisassembleAddress(FILE* file) const;
|
||||||
|
|
||||||
void CopyMode(const NativeCodeInstruction& ins);
|
void CopyMode(const NativeCodeInstruction& ins);
|
||||||
|
void CopyModeAndRange(const NativeCodeInstruction& ins);
|
||||||
|
|
||||||
void Assemble(NativeCodeBasicBlock* block);
|
void Assemble(NativeCodeBasicBlock* block);
|
||||||
void FilterRegUsage(NumberSet& requiredTemps, NumberSet& providedTemps);
|
void FilterRegUsage(NumberSet& requiredTemps, NumberSet& providedTemps);
|
||||||
|
@ -191,6 +205,7 @@ public:
|
||||||
bool UsesZeroPage(int address) const;
|
bool UsesZeroPage(int address) const;
|
||||||
bool ReferencesZeroPage(int address) const;
|
bool ReferencesZeroPage(int address) const;
|
||||||
|
|
||||||
|
bool SameLinkerObjectVariableRange(const NativeCodeInstruction& ins, bool sameXY = false) const;
|
||||||
|
|
||||||
bool ChangesGlobalMemory(void) const;
|
bool ChangesGlobalMemory(void) const;
|
||||||
bool UsesMemoryOf(const NativeCodeInstruction& ins) const;
|
bool UsesMemoryOf(const NativeCodeInstruction& ins) const;
|
||||||
|
@ -205,7 +220,7 @@ public:
|
||||||
bool IsShift(void) const;
|
bool IsShift(void) const;
|
||||||
bool IsShiftOrInc(void) const;
|
bool IsShiftOrInc(void) const;
|
||||||
bool IsSimpleJSR(void) const;
|
bool IsSimpleJSR(void) const;
|
||||||
bool MayBeMovedBefore(const NativeCodeInstruction& ins);
|
bool MayBeMovedBefore(const NativeCodeInstruction& ins) const;
|
||||||
|
|
||||||
bool ReplaceYRegWithXReg(void);
|
bool ReplaceYRegWithXReg(void);
|
||||||
bool ReplaceXRegWithYReg(void);
|
bool ReplaceXRegWithYReg(void);
|
||||||
|
@ -216,6 +231,12 @@ public:
|
||||||
void BuildCollisionTable(NumberSet& liveTemps, NumberSet* collisionSets);
|
void BuildCollisionTable(NumberSet& liveTemps, NumberSet* collisionSets);
|
||||||
|
|
||||||
uint32 NeedsLive(void) const;
|
uint32 NeedsLive(void) const;
|
||||||
|
|
||||||
|
uint32 CodeHash(void) const;
|
||||||
|
bool CodeSame(const NativeCodeInstruction& ins);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const char* AddrName(char* buffer) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NativeCodeLoadStorePair
|
struct NativeCodeLoadStorePair
|
||||||
|
@ -246,7 +267,7 @@ public:
|
||||||
ExpandingArray<NativeCodeBasicBlock*> mEntryBlocks;
|
ExpandingArray<NativeCodeBasicBlock*> mEntryBlocks;
|
||||||
|
|
||||||
int mOffset, mSize, mPlace, mNumEntries, mNumEntered, mFrameOffset, mTemp;
|
int mOffset, mSize, mPlace, mNumEntries, mNumEntered, mFrameOffset, mTemp;
|
||||||
bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mNoFrame, mVisited, mLoopHead, mVisiting, mLocked, mPatched, mPatchFail, mPatchChecked, mPatchStart, mPatchLoop, mPatchLoopChanged, mPatchExit;
|
bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mNoFrame, mVisited, mLoopHead, mVisiting, mLocked, mPatched, mPatchFail, mPatchChecked, mPatchUsed, mPatchStart, mPatchLoop, mPatchLoopChanged, mPatchExit;
|
||||||
bool mEntryRegA, mEntryRegX, mEntryRegY, mExitRegA, mExitRegX, mChecked;
|
bool mEntryRegA, mEntryRegX, mEntryRegY, mExitRegA, mExitRegX, mChecked;
|
||||||
NativeCodeBasicBlock * mDominator, * mSameBlock;
|
NativeCodeBasicBlock * mDominator, * mSameBlock;
|
||||||
|
|
||||||
|
@ -264,12 +285,16 @@ public:
|
||||||
|
|
||||||
NativeCodeInstruction mALSIns, mXLSIns, mYLSIns;
|
NativeCodeInstruction mALSIns, mXLSIns, mYLSIns;
|
||||||
|
|
||||||
|
void Disassemble(FILE* file);
|
||||||
|
void DisassembleBody(FILE* file);
|
||||||
|
|
||||||
NativeCodeInstruction DecodeNative(const InterInstruction* ins, LinkerObject * lobj, int& offset) const;
|
NativeCodeInstruction DecodeNative(const InterInstruction* ins, LinkerObject * lobj, int& offset) const;
|
||||||
|
|
||||||
int PutBranch(NativeCodeProcedure* proc, NativeCodeBasicBlock* target, AsmInsType code, int from, int to);
|
int PutBranch(NativeCodeProcedure* proc, NativeCodeBasicBlock* target, AsmInsType code, int from, int to);
|
||||||
int PutJump(NativeCodeProcedure* proc, NativeCodeBasicBlock* target, int from, int to, AsmInsType code = ASMIT_INV);
|
int PutJump(NativeCodeProcedure* proc, NativeCodeBasicBlock* target, int from, int to, AsmInsType code = ASMIT_INV);
|
||||||
int JumpByteSize(NativeCodeBasicBlock * target, int from, int to, bool second, bool final);
|
int JumpByteSize(NativeCodeBasicBlock * target, int from, int to, bool second, bool final);
|
||||||
int BranchByteSize(NativeCodeBasicBlock* target, int from, int to, bool final);
|
int CheckFinalBranchByteSize(NativeCodeBasicBlock* target, int from, int to) const;
|
||||||
|
int BranchByteSize(NativeCodeBasicBlock* target, int from, int to, bool final) const;
|
||||||
|
|
||||||
NativeCodeBasicBlock* SplitAt(int at);
|
NativeCodeBasicBlock* SplitAt(int at);
|
||||||
|
|
||||||
|
@ -278,6 +303,7 @@ public:
|
||||||
int LeadsInto(NativeCodeBasicBlock* block, int dist);
|
int LeadsInto(NativeCodeBasicBlock* block, int dist);
|
||||||
NativeCodeBasicBlock* PlaceSequence(ExpandingArray<NativeCodeBasicBlock*>& placement, NativeCodeBasicBlock* block);
|
NativeCodeBasicBlock* PlaceSequence(ExpandingArray<NativeCodeBasicBlock*>& placement, NativeCodeBasicBlock* block);
|
||||||
void BuildPlacement(ExpandingArray<NativeCodeBasicBlock*>& placement);
|
void BuildPlacement(ExpandingArray<NativeCodeBasicBlock*>& placement);
|
||||||
|
void OptimizePlacement(void);
|
||||||
void InitialOffset(int& total);
|
void InitialOffset(int& total);
|
||||||
bool CalculateOffset(int& total, bool final);
|
bool CalculateOffset(int& total, bool final);
|
||||||
|
|
||||||
|
@ -302,6 +328,8 @@ public:
|
||||||
bool UsesZeroPage(int address, int from = 0, int to = 65536) const;
|
bool UsesZeroPage(int address, int from = 0, int to = 65536) const;
|
||||||
bool ReferencesZeroPage(int address, int from = 0, int to = 65536) const;
|
bool ReferencesZeroPage(int address, int from = 0, int to = 65536) const;
|
||||||
|
|
||||||
|
bool ChangesMemory(const NativeCodeInstruction& ins, int from = 0, int to = 65536) const;
|
||||||
|
bool ReferencesMemory(const NativeCodeInstruction& ins, int from = 0, int to = 65536) const;
|
||||||
|
|
||||||
bool RemoveNops(void);
|
bool RemoveNops(void);
|
||||||
bool PeepHoleOptimizer(int pass);
|
bool PeepHoleOptimizer(int pass);
|
||||||
|
@ -320,18 +348,20 @@ public:
|
||||||
bool PeepHoleOptimizerIterate(int pass);
|
bool PeepHoleOptimizerIterate(int pass);
|
||||||
bool PeepHoleOptimizerExits(int pass);
|
bool PeepHoleOptimizerExits(int pass);
|
||||||
|
|
||||||
void BlockSizeReduction(NativeCodeProcedure* proc, int xenter, int yenter);
|
void BlockSizeReduction(NativeCodeProcedure* proc, int xenter, int yenter, int center);
|
||||||
bool BlockSizeCopyReduction(NativeCodeProcedure* proc, int & si, int & di);
|
bool BlockSizeCopyReduction(NativeCodeProcedure* proc, int & si, int & di);
|
||||||
|
|
||||||
bool OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc, bool full);
|
bool OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc, bool full);
|
||||||
bool OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc, NativeCodeBasicBlock * prevBlock, NativeCodeBasicBlock* exitBlock, bool full);
|
bool OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc, NativeCodeBasicBlock * prevBlock, NativeCodeBasicBlock* exitBlock, bool full);
|
||||||
bool RemoveSimpleLoopUnusedIndex(void);
|
bool RemoveSimpleLoopUnusedIndex(void);
|
||||||
bool OptimizeLoopCarryOver(void);
|
bool OptimizeLoopCarryOver(void);
|
||||||
|
bool OptimizeLoopRegisterWrapAround(void);
|
||||||
|
|
||||||
bool OptimizeSingleEntryLoopInvariant(NativeCodeProcedure* proc, NativeCodeBasicBlock* prev, NativeCodeBasicBlock* tail, ExpandingArray<NativeCodeBasicBlock*>& blocks);
|
bool OptimizeSingleEntryLoopInvariant(NativeCodeProcedure* proc, NativeCodeBasicBlock* prev, NativeCodeBasicBlock* tail, ExpandingArray<NativeCodeBasicBlock*>& blocks);
|
||||||
bool OptimizeSingleEntryLoop(NativeCodeProcedure* proc);
|
bool OptimizeSingleEntryLoop(NativeCodeProcedure* proc);
|
||||||
|
|
||||||
bool OptimizeSimpleLoop(NativeCodeProcedure* proc, bool full);
|
bool OptimizeSimpleLoop(NativeCodeProcedure* proc, bool full);
|
||||||
|
bool OptimizeSimpleForLoop(void);
|
||||||
bool SimpleLoopReversal(NativeCodeProcedure* proc);
|
bool SimpleLoopReversal(NativeCodeProcedure* proc);
|
||||||
bool OptimizeInnerLoop(NativeCodeProcedure* proc, NativeCodeBasicBlock* head, NativeCodeBasicBlock* tail, ExpandingArray<NativeCodeBasicBlock*>& blocks);
|
bool OptimizeInnerLoop(NativeCodeProcedure* proc, NativeCodeBasicBlock* head, NativeCodeBasicBlock* tail, ExpandingArray<NativeCodeBasicBlock*>& blocks);
|
||||||
bool OptimizeXYSimpleLoop(void);
|
bool OptimizeXYSimpleLoop(void);
|
||||||
|
@ -343,9 +373,11 @@ public:
|
||||||
bool OptimizeInnerLoops(NativeCodeProcedure* proc);
|
bool OptimizeInnerLoops(NativeCodeProcedure* proc);
|
||||||
NativeCodeBasicBlock* CollectInnerLoop(NativeCodeBasicBlock* head, ExpandingArray<NativeCodeBasicBlock*>& lblocks);
|
NativeCodeBasicBlock* CollectInnerLoop(NativeCodeBasicBlock* head, ExpandingArray<NativeCodeBasicBlock*>& lblocks);
|
||||||
|
|
||||||
bool OptimizeGenericLoop(NativeCodeProcedure* proc);
|
int CorrectXOffset(const InterInstruction * ins, int yoffset, int at);
|
||||||
bool CollectGenericLoop(NativeCodeProcedure* proc, ExpandingArray<NativeCodeBasicBlock*>& lblocks);
|
int CorrectYOffset(const InterInstruction * ins, int yoffset, int at);
|
||||||
bool CollectSingleEntryGenericLoop(NativeCodeProcedure* proc, ExpandingArray<NativeCodeBasicBlock*>& lblocks);
|
bool OptimizeGenericLoop(void);
|
||||||
|
bool CollectGenericLoop(ExpandingArray<NativeCodeBasicBlock*>& lblocks);
|
||||||
|
bool CollectSingleEntryGenericLoop(ExpandingArray<NativeCodeBasicBlock*>& lblocks);
|
||||||
void CollectReachable(ExpandingArray<NativeCodeBasicBlock*>& lblock);
|
void CollectReachable(ExpandingArray<NativeCodeBasicBlock*>& lblock);
|
||||||
|
|
||||||
bool OptimizeFindLoop(NativeCodeProcedure* proc);
|
bool OptimizeFindLoop(NativeCodeProcedure* proc);
|
||||||
|
@ -379,7 +411,7 @@ public:
|
||||||
NativeCodeBasicBlock* BinaryOperator(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins, const InterInstruction* sins1, const InterInstruction* sins0);
|
NativeCodeBasicBlock* BinaryOperator(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins, const InterInstruction* sins1, const InterInstruction* sins0);
|
||||||
void UnaryOperator(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins);
|
void UnaryOperator(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins);
|
||||||
void RelationalOperator(InterCodeProcedure* proc, const InterInstruction * ins, NativeCodeProcedure * nproc, NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock * falseJump);
|
void RelationalOperator(InterCodeProcedure* proc, const InterInstruction * ins, NativeCodeProcedure * nproc, NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock * falseJump);
|
||||||
void LoadEffectiveAddress(InterCodeProcedure* proc, const InterInstruction * ins, const InterInstruction* sins1, const InterInstruction* sins0, bool addrvalid);
|
void LoadEffectiveAddress(InterCodeProcedure* proc, const InterInstruction * ins, const InterInstruction* sins1, const InterInstruction* sins0, bool addrvalid, bool addrused = false);
|
||||||
void LoadStoreOpAbsolute2D(InterCodeProcedure* proc, const InterInstruction* lins1, const InterInstruction* lins2, const InterInstruction* mins);
|
void LoadStoreOpAbsolute2D(InterCodeProcedure* proc, const InterInstruction* lins1, const InterInstruction* lins2, const InterInstruction* mins);
|
||||||
void SignExtendAddImmediate(InterCodeProcedure* proc, const InterInstruction* xins, const InterInstruction* ains);
|
void SignExtendAddImmediate(InterCodeProcedure* proc, const InterInstruction* xins, const InterInstruction* ains);
|
||||||
void BinaryDivModPair(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction* ins1, const InterInstruction* ins2);
|
void BinaryDivModPair(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction* ins1, const InterInstruction* ins2);
|
||||||
|
@ -396,6 +428,7 @@ public:
|
||||||
|
|
||||||
void LoadByteIndexedValue(InterCodeProcedure* proc, const InterInstruction* iins, const InterInstruction* rins);
|
void LoadByteIndexedValue(InterCodeProcedure* proc, const InterInstruction* iins, const InterInstruction* rins);
|
||||||
void StoreByteIndexedValue(InterCodeProcedure* proc, const InterInstruction* iins, const InterInstruction* rins);
|
void StoreByteIndexedValue(InterCodeProcedure* proc, const InterInstruction* iins, const InterInstruction* rins);
|
||||||
|
void CopyByteIndexedValue(InterCodeProcedure* proc, const InterInstruction* riins, const InterInstruction* wiins, const InterInstruction* rins, const InterInstruction* wins);
|
||||||
|
|
||||||
void CallAssembler(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins);
|
void CallAssembler(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins);
|
||||||
void CallFunction(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins);
|
void CallFunction(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins);
|
||||||
|
@ -408,6 +441,7 @@ public:
|
||||||
int ShortSignedDivide(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction* ins, const InterInstruction* sins, int mul);
|
int ShortSignedDivide(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction* ins, const InterInstruction* sins, int mul);
|
||||||
|
|
||||||
bool CheckPredAccuStore(int reg);
|
bool CheckPredAccuStore(int reg);
|
||||||
|
bool CheckIsInAccu(int reg);
|
||||||
|
|
||||||
NumberSet mLocalRequiredRegs, mLocalProvidedRegs;
|
NumberSet mLocalRequiredRegs, mLocalProvidedRegs;
|
||||||
NumberSet mEntryRequiredRegs, mEntryProvidedRegs;
|
NumberSet mEntryRequiredRegs, mEntryProvidedRegs;
|
||||||
|
@ -429,9 +463,7 @@ public:
|
||||||
void CountEntries(NativeCodeBasicBlock* fromJump);
|
void CountEntries(NativeCodeBasicBlock* fromJump);
|
||||||
NativeCodeBasicBlock * ForwardAccuBranch(bool eq, bool ne, bool pl, bool mi, int limit);
|
NativeCodeBasicBlock * ForwardAccuBranch(bool eq, bool ne, bool pl, bool mi, int limit);
|
||||||
bool MergeBasicBlocks(void);
|
bool MergeBasicBlocks(void);
|
||||||
void RemoveJumpToBranch(void);
|
bool RemoveJumpToBranch(void);
|
||||||
|
|
||||||
void MarkLoopHead(void);
|
|
||||||
|
|
||||||
struct DominatorStacks
|
struct DominatorStacks
|
||||||
{
|
{
|
||||||
|
@ -505,7 +537,9 @@ public:
|
||||||
bool CombineImmediateADCUp(int at);
|
bool CombineImmediateADCUp(int at);
|
||||||
bool CombineImmediateADCUpX(int at);
|
bool CombineImmediateADCUpX(int at);
|
||||||
bool MoveTXADCDown(int at);
|
bool MoveTXADCDown(int at);
|
||||||
|
bool MoveTXALogicTAXDown(int at);
|
||||||
bool FoldShiftORAIntoLoadImmUp(int at);
|
bool FoldShiftORAIntoLoadImmUp(int at);
|
||||||
|
bool ReverseShiftByteOrder(int at);
|
||||||
|
|
||||||
bool FindAccuExitValue(int& at);
|
bool FindAccuExitValue(int& at);
|
||||||
bool MoveLoadXAbsUpCrossBlock(int at);
|
bool MoveLoadXAbsUpCrossBlock(int at);
|
||||||
|
@ -539,6 +573,7 @@ public:
|
||||||
bool CombineSameYtoX(int xpos, int ypos, int end);
|
bool CombineSameYtoX(int xpos, int ypos, int end);
|
||||||
|
|
||||||
bool FindImmediateStore(int at, int reg, const NativeCodeInstruction*& ains);
|
bool FindImmediateStore(int at, int reg, const NativeCodeInstruction*& ains);
|
||||||
|
int FindImmediateGlobalStore(int at, const NativeCodeInstruction& ins);
|
||||||
|
|
||||||
bool JoinXYCrossBlock(void);
|
bool JoinXYCrossBlock(void);
|
||||||
bool CanCombineSameXtoYCrossBlock(int from);
|
bool CanCombineSameXtoYCrossBlock(int from);
|
||||||
|
@ -559,6 +594,13 @@ public:
|
||||||
|
|
||||||
bool ReverseReplaceTAX(int at);
|
bool ReverseReplaceTAX(int at);
|
||||||
|
|
||||||
|
bool CanReplaceExitAccuWithX(NativeCodeBasicBlock * target);
|
||||||
|
bool CanReplaceExitAccuWithY(NativeCodeBasicBlock* target);
|
||||||
|
void ReplaceExitAccuWithX(NativeCodeBasicBlock* target);
|
||||||
|
void ReplaceExitAccuWithY(NativeCodeBasicBlock* target);
|
||||||
|
|
||||||
|
bool ReverseLoadAccuToRegXY(void);
|
||||||
|
|
||||||
void ResetModifiedDataSet(NativeRegisterDataSet& data);
|
void ResetModifiedDataSet(NativeRegisterDataSet& data);
|
||||||
|
|
||||||
bool ValueForwarding(NativeCodeProcedure* proc, const NativeRegisterDataSet& data, bool global, bool final);
|
bool ValueForwarding(NativeCodeProcedure* proc, const NativeRegisterDataSet& data, bool global, bool final);
|
||||||
|
@ -568,6 +610,9 @@ public:
|
||||||
bool OffsetValueForwarding(const ValueNumberingDataSet & data);
|
bool OffsetValueForwarding(const ValueNumberingDataSet & data);
|
||||||
bool AbsoluteValueForwarding(const ExpandingArray<NativeCodeLoadStorePair>& npairs);
|
bool AbsoluteValueForwarding(const ExpandingArray<NativeCodeLoadStorePair>& npairs);
|
||||||
bool IndexXYValueForwarding(int xreg, int xoffset, int xvalue, int yreg, int yoffset, int yvalue);
|
bool IndexXYValueForwarding(int xreg, int xoffset, int xvalue, int yreg, int yoffset, int yvalue);
|
||||||
|
bool ReduceIndexXYZeroShuffle(NativeCodeBasicBlock* from, int xreg, int yreg);
|
||||||
|
bool CheckLoopIndexXRegisters(NativeCodeBasicBlock* head, int xreg);
|
||||||
|
bool CheckLoopIndexYRegisters(NativeCodeBasicBlock* head, int yreg);
|
||||||
|
|
||||||
void MarkLocalUsedLinkerObjects(void);
|
void MarkLocalUsedLinkerObjects(void);
|
||||||
bool RemoveLocalUnusedLinkerObjects(void);
|
bool RemoveLocalUnusedLinkerObjects(void);
|
||||||
|
@ -587,7 +632,14 @@ public:
|
||||||
bool HasTailSTY(int& addr, int& index) const;
|
bool HasTailSTY(int& addr, int& index) const;
|
||||||
bool HasTailSTAX16(int& addr, int& index0) const;
|
bool HasTailSTAX16(int& addr, int& index0) const;
|
||||||
|
|
||||||
|
bool HasTailSTAInto(int& addr, int& index, NativeCodeBasicBlock* tblock) const;
|
||||||
|
bool HasTailSTXInto(int& addr, int& index, NativeCodeBasicBlock* tblock) const;
|
||||||
|
bool HasTailSTYInto(int& addr, int& index, NativeCodeBasicBlock* tblock) const;
|
||||||
|
|
||||||
|
bool HasTailSTAGlobal(NativeCodeInstruction & ins, int& index) const;
|
||||||
|
|
||||||
bool MayBeMovedBeforeBlock(int at);
|
bool MayBeMovedBeforeBlock(int at);
|
||||||
|
bool MayBeMovedBeforeBlock(int at, const NativeCodeInstruction & ins);
|
||||||
bool MayBeMovedBeforeBlock(int start, int end);
|
bool MayBeMovedBeforeBlock(int start, int end);
|
||||||
bool SafeInjectSequenceFromBack(NativeCodeBasicBlock* block, int start, int end);
|
bool SafeInjectSequenceFromBack(NativeCodeBasicBlock* block, int start, int end);
|
||||||
bool JoinCommonBranchCodeSequences(void);
|
bool JoinCommonBranchCodeSequences(void);
|
||||||
|
@ -691,6 +743,8 @@ public:
|
||||||
bool EliminateDeadLoops(void);
|
bool EliminateDeadLoops(void);
|
||||||
bool LoopRegisterWrapAround(void);
|
bool LoopRegisterWrapAround(void);
|
||||||
bool CrossBlockFlagsForwarding(void);
|
bool CrossBlockFlagsForwarding(void);
|
||||||
|
bool MoveStoresBeforeDiamond(void);
|
||||||
|
bool MoveStoresBehindCondition(void);
|
||||||
|
|
||||||
bool SinglePathRegisterForwardY(NativeCodeBasicBlock* path, int yreg);
|
bool SinglePathRegisterForwardY(NativeCodeBasicBlock* path, int yreg);
|
||||||
bool SinglePathRegisterForward(void);
|
bool SinglePathRegisterForward(void);
|
||||||
|
@ -723,8 +777,9 @@ public:
|
||||||
bool CanGlobalSwapXY(void);
|
bool CanGlobalSwapXY(void);
|
||||||
bool GlobalSwapXY(void);
|
bool GlobalSwapXY(void);
|
||||||
bool LocalSwapXY(void);
|
bool LocalSwapXY(void);
|
||||||
bool UntangleXYUsage(void);
|
bool UntangleXYUsage(bool final);
|
||||||
bool AlternateXXUsage(void);
|
bool AlternateXXUsage(void);
|
||||||
|
bool ShortSwapXY(void);
|
||||||
|
|
||||||
bool IsSimpleSubExpression(int at, NativeSimpleSubExpression & ex);
|
bool IsSimpleSubExpression(int at, NativeSimpleSubExpression & ex);
|
||||||
bool PropagateCommonSubExpression(void);
|
bool PropagateCommonSubExpression(void);
|
||||||
|
@ -748,10 +803,20 @@ public:
|
||||||
bool CheckPatchFailUse(void);
|
bool CheckPatchFailUse(void);
|
||||||
|
|
||||||
bool CheckPatchFailLoop(const NativeCodeBasicBlock* block, const NativeCodeBasicBlock* head, int reg, bool changed);
|
bool CheckPatchFailLoop(const NativeCodeBasicBlock* block, const NativeCodeBasicBlock* head, int reg, bool changed);
|
||||||
|
bool CheckPatchFailLoopPair(const NativeCodeBasicBlock* block, const NativeCodeBasicBlock* head, int reg, bool changed);
|
||||||
|
|
||||||
bool JoinSameBranch(NativeCodeBasicBlock* block);
|
bool JoinSameBranch(NativeCodeBasicBlock* block);
|
||||||
bool MergeSameBranch(void);
|
bool MergeSameBranch(void);
|
||||||
|
|
||||||
|
bool CheckBoolBitPropagation(const NativeCodeBasicBlock* block, int at, int reg);
|
||||||
|
bool PatchBoolBitPropagation(const NativeCodeBasicBlock* block, int at, int reg);
|
||||||
|
|
||||||
|
bool CollectRegBoolInstructionsForward(int reg, ExpandingArray<NativeCodeBasicBlock*>& cblocks, ExpandingArray<NativeCodeInstruction*>& lins);
|
||||||
|
bool CollectRegBoolInstructionsBackward(int reg, ExpandingArray<NativeCodeBasicBlock*>& cblocks, ExpandingArray<NativeCodeInstruction*>& lins);
|
||||||
|
|
||||||
|
bool CollectCheckRegOriginBlocks(int at, int reg, ExpandingArray<NativeCodeBasicBlock*>& lblocks, ExpandingArray<NativeCodeInstruction*>& lins);
|
||||||
|
bool PatchBitBoolConstOrigin(void);
|
||||||
|
|
||||||
// reg : base register pair to replace
|
// reg : base register pair to replace
|
||||||
// index: index register
|
// index: index register
|
||||||
// at : start position in block
|
// at : start position in block
|
||||||
|
@ -761,9 +826,20 @@ public:
|
||||||
bool CheckGlobalAddressSumYPointer(const NativeCodeBasicBlock * block, int reg, int index, int at, int yval);
|
bool CheckGlobalAddressSumYPointer(const NativeCodeBasicBlock * block, int reg, int index, int at, int yval);
|
||||||
bool PatchGlobalAddressSumYPointer(const NativeCodeBasicBlock* block, int reg, int index, int at, int yval, LinkerObject * lobj, int address, uint32 flags = NCIF_LOWER | NCIF_UPPER);
|
bool PatchGlobalAddressSumYPointer(const NativeCodeBasicBlock* block, int reg, int index, int at, int yval, LinkerObject * lobj, int address, uint32 flags = NCIF_LOWER | NCIF_UPPER);
|
||||||
|
|
||||||
|
// reg : register to replace
|
||||||
|
// at : start position in block
|
||||||
|
// ains : instruction loading original data
|
||||||
|
// cycles : max number of cycles saving
|
||||||
bool CheckSingleUseGlobalLoad(const NativeCodeBasicBlock* block, int reg, int at, const NativeCodeInstruction& ains, int cycles);
|
bool CheckSingleUseGlobalLoad(const NativeCodeBasicBlock* block, int reg, int at, const NativeCodeInstruction& ains, int cycles);
|
||||||
bool PatchSingleUseGlobalLoad(const NativeCodeBasicBlock* block, int reg, int at, const NativeCodeInstruction& ains);
|
bool PatchSingleUseGlobalLoad(const NativeCodeBasicBlock* block, int reg, int at, const NativeCodeInstruction& ains);
|
||||||
|
|
||||||
|
// rins : instruction storing the data
|
||||||
|
// at : start position in block
|
||||||
|
// ains : instruction loading original data
|
||||||
|
// cycles : max number of cycles saving
|
||||||
|
bool CheckSingleUseGlobalLoadStruct(const NativeCodeBasicBlock* block, const NativeCodeInstruction& rins, int at, const NativeCodeInstruction& ains, bool cleared, bool poisoned);
|
||||||
|
bool PatchSingleUseGlobalLoadStruct(const NativeCodeBasicBlock* block, const NativeCodeInstruction& rins, int at, const NativeCodeInstruction& ains);
|
||||||
|
|
||||||
// reg : base register pair to replace
|
// reg : base register pair to replace
|
||||||
// base: new base register
|
// base: new base register
|
||||||
// iins : indexing instruction
|
// iins : indexing instruction
|
||||||
|
@ -807,6 +883,10 @@ public:
|
||||||
|
|
||||||
void PropagateAddGlobalCarry(void);
|
void PropagateAddGlobalCarry(void);
|
||||||
|
|
||||||
|
bool EliminateNonAliasedLocalStores(void);
|
||||||
|
bool CheckNonAliasedLocalStore(int at, const NativeCodeInstruction& sins);
|
||||||
|
|
||||||
|
|
||||||
void RegisterFunctionCalls(void);
|
void RegisterFunctionCalls(void);
|
||||||
bool MergeFunctionCalls(void);
|
bool MergeFunctionCalls(void);
|
||||||
|
|
||||||
|
@ -816,6 +896,9 @@ public:
|
||||||
void CheckBlocks(bool sequence = false);
|
void CheckBlocks(bool sequence = false);
|
||||||
void CheckAsmCode(void);
|
void CheckAsmCode(void);
|
||||||
void CheckVisited(void);
|
void CheckVisited(void);
|
||||||
|
|
||||||
|
int* mSuffixString;
|
||||||
|
void AddToSuffixTree(NativeCodeMapper& mapper, SuffixTree * tree);
|
||||||
};
|
};
|
||||||
|
|
||||||
class NativeCodeProcedure
|
class NativeCodeProcedure
|
||||||
|
@ -830,6 +913,10 @@ class NativeCodeProcedure
|
||||||
NativeCodeGenerator* mGenerator;
|
NativeCodeGenerator* mGenerator;
|
||||||
|
|
||||||
InterCodeProcedure* mInterProc;
|
InterCodeProcedure* mInterProc;
|
||||||
|
LinkerObject* mLinkerObject;
|
||||||
|
const Ident* mIdent;
|
||||||
|
Location mLocation;
|
||||||
|
uint64 mCompilerOptions;
|
||||||
|
|
||||||
int mProgStart, mProgSize, mIndex, mFrameOffset, mStackExpand;
|
int mProgStart, mProgSize, mIndex, mFrameOffset, mStackExpand;
|
||||||
int mFastCallBase;
|
int mFastCallBase;
|
||||||
|
@ -841,10 +928,15 @@ class NativeCodeProcedure
|
||||||
ExpandingArray<CodeLocation> mCodeLocations;
|
ExpandingArray<CodeLocation> mCodeLocations;
|
||||||
|
|
||||||
|
|
||||||
|
void DisassembleDebug(const char* name);
|
||||||
|
void Disassemble(FILE* file);
|
||||||
|
|
||||||
void Compile(InterCodeProcedure* proc);
|
void Compile(InterCodeProcedure* proc);
|
||||||
void Optimize(void);
|
void Optimize(void);
|
||||||
void Assemble(void);
|
void Assemble(void);
|
||||||
|
|
||||||
|
void AddToSuffixTree(NativeCodeMapper& mapper, SuffixTree* tree);
|
||||||
|
|
||||||
NativeCodeBasicBlock* CompileBlock(InterCodeProcedure* iproc, InterCodeBasicBlock* block);
|
NativeCodeBasicBlock* CompileBlock(InterCodeProcedure* iproc, InterCodeBasicBlock* block);
|
||||||
NativeCodeBasicBlock* AllocateBlock(void);
|
NativeCodeBasicBlock* AllocateBlock(void);
|
||||||
|
|
||||||
|
@ -910,6 +1002,8 @@ public:
|
||||||
Linker* mLinker;
|
Linker* mLinker;
|
||||||
LinkerSection* mRuntimeSection;
|
LinkerSection* mRuntimeSection;
|
||||||
|
|
||||||
|
ExpandingArray<NativeCodeProcedure*> mProcedures;
|
||||||
|
|
||||||
ExpandingArray<Runtime> mRuntime;
|
ExpandingArray<Runtime> mRuntime;
|
||||||
ExpandingArray<MulTable> mMulTables;
|
ExpandingArray<MulTable> mMulTables;
|
||||||
ExpandingArray<FloatTable> mFloatTables;
|
ExpandingArray<FloatTable> mFloatTables;
|
||||||
|
@ -928,6 +1022,8 @@ public:
|
||||||
|
|
||||||
FunctionCall* mFunctionCalls;
|
FunctionCall* mFunctionCalls;
|
||||||
|
|
||||||
|
void OutlineFunctions(void);
|
||||||
|
|
||||||
void RegisterFunctionCall(NativeCodeBasicBlock* block, int at);
|
void RegisterFunctionCall(NativeCodeBasicBlock* block, int at);
|
||||||
void BuildFunctionProxies(void);
|
void BuildFunctionProxies(void);
|
||||||
bool MergeFunctionCall(NativeCodeBasicBlock* block, int at);
|
bool MergeFunctionCall(NativeCodeBasicBlock* block, int at);
|
||||||
|
|
|
@ -0,0 +1,379 @@
|
||||||
|
#include "NativeCodeOutliner.h"
|
||||||
|
|
||||||
|
|
||||||
|
NativeCodeMapper::NativeCodeMapper(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < HashSize; i++)
|
||||||
|
mHash[i] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
NativeCodeMapper::~NativeCodeMapper(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < HashSize; i++)
|
||||||
|
{
|
||||||
|
InsNode* n = mHash[i];
|
||||||
|
while (n)
|
||||||
|
{
|
||||||
|
InsNode* m = n;
|
||||||
|
n = n->mNext;
|
||||||
|
delete m;
|
||||||
|
}
|
||||||
|
mHash[i] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void NativeCodeMapper::Reset(void)
|
||||||
|
{
|
||||||
|
mBlocks.SetSize(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int NativeCodeMapper::MapBasicBlock(NativeCodeBasicBlock* block)
|
||||||
|
{
|
||||||
|
mBlocks.Push(block);
|
||||||
|
return -mBlocks.Size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int NativeCodeMapper::MapInstruction(const NativeCodeInstruction& ins, LinkerSection* ls)
|
||||||
|
{
|
||||||
|
int hash = ins.CodeHash() % HashSize;
|
||||||
|
InsNode* n = mHash[hash];
|
||||||
|
while (n)
|
||||||
|
{
|
||||||
|
if (mIns[n->mIndex].CodeSame(ins) && n->mSection == ls)
|
||||||
|
return n->mIndex;
|
||||||
|
n = n->mNext;
|
||||||
|
}
|
||||||
|
n = new InsNode();
|
||||||
|
n->mIndex = mIns.Size();
|
||||||
|
n->mSection = ls;
|
||||||
|
mIns.Push(ins);
|
||||||
|
n->mNext = mHash[hash];
|
||||||
|
mHash[hash] = n;
|
||||||
|
return n->mIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
SuffixTree::SuffixTree(const int* str, int s, SuffixTree* n)
|
||||||
|
{
|
||||||
|
mSeg = str;
|
||||||
|
mSize = s;
|
||||||
|
mNext = n;
|
||||||
|
mParent = nullptr;
|
||||||
|
mFirst = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
SuffixTree::~SuffixTree(void)
|
||||||
|
{
|
||||||
|
delete[] mFirst;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuffixTree::AddParents(SuffixTree* parent)
|
||||||
|
{
|
||||||
|
mParent = parent;
|
||||||
|
if (mFirst)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < HashSize; i++)
|
||||||
|
{
|
||||||
|
SuffixTree* n = mFirst[i];
|
||||||
|
while (n)
|
||||||
|
{
|
||||||
|
n->AddParents(this);
|
||||||
|
n = n->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuffixTree::AddSuffix(const int* str, int s)
|
||||||
|
{
|
||||||
|
int hi = str[0] & (HashSize - 1);
|
||||||
|
SuffixTree* c = mFirst ? mFirst[hi] : nullptr;
|
||||||
|
while (c && c->mSeg[0] != str[0])
|
||||||
|
c = c->mNext;
|
||||||
|
|
||||||
|
if (c)
|
||||||
|
{
|
||||||
|
int k = 1;
|
||||||
|
while (k < c->mSize && str[k] == c->mSeg[k])
|
||||||
|
k++;
|
||||||
|
if (k == c->mSize)
|
||||||
|
c->AddSuffix(str + k, s - k);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SuffixTree * n = new SuffixTree(c->mSeg + k, c->mSize - k, nullptr);
|
||||||
|
if (c->mFirst)
|
||||||
|
{
|
||||||
|
n->mFirst = new SuffixTree * [HashSize];
|
||||||
|
for (int i = 0; i < HashSize; i++)
|
||||||
|
{
|
||||||
|
n->mFirst[i] = c->mFirst[i];
|
||||||
|
c->mFirst[i] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c->mFirst = new SuffixTree * [HashSize];
|
||||||
|
for (int i = 0; i < HashSize; i++)
|
||||||
|
c->mFirst[i] = nullptr;
|
||||||
|
}
|
||||||
|
c->mFirst[c->mSeg[k] & (HashSize - 1)] = n;
|
||||||
|
int hk = str[k] & (HashSize - 1);
|
||||||
|
c->mFirst[hk] = new SuffixTree(str + k, s - k, c->mFirst[hk]);
|
||||||
|
c->mSize = k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!mFirst)
|
||||||
|
{
|
||||||
|
mFirst = new SuffixTree * [HashSize];
|
||||||
|
for (int i = 0; i < HashSize; i++)
|
||||||
|
mFirst[i] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
mFirst[hi] = new SuffixTree(str, s, mFirst[hi]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuffixTree::AddString(const int* str)
|
||||||
|
{
|
||||||
|
int s = 0;
|
||||||
|
while(str[s] >= 0)
|
||||||
|
s++;
|
||||||
|
s++;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
while (str[i] >= 0)
|
||||||
|
{
|
||||||
|
AddSuffix(str + i, s - i);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
AddSuffix(str + i, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuffixTree::CollectSuffix(NativeCodeMapper& map, int offset, ExpandingArray<SuffixSegment>& segs)
|
||||||
|
{
|
||||||
|
offset += mSize;
|
||||||
|
if (mFirst)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < HashSize; i++)
|
||||||
|
{
|
||||||
|
SuffixTree* t = mFirst[i];
|
||||||
|
|
||||||
|
while (t)
|
||||||
|
{
|
||||||
|
t->CollectSuffix(map, offset, segs);
|
||||||
|
t = t->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NativeCodeBasicBlock* block = map.mBlocks[-(mSeg[mSize - 1] + 1)];
|
||||||
|
|
||||||
|
SuffixSegment seg;
|
||||||
|
seg.mBlock = block;
|
||||||
|
seg.mStart = offset;
|
||||||
|
seg.mEnd = block->mIns.Size() + 1;
|
||||||
|
segs.Push(seg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int SuffixTree::LongestMatch(NativeCodeMapper& map, int size, int isize, int& msize, SuffixTree*& mtree)
|
||||||
|
{
|
||||||
|
if (mFirst)
|
||||||
|
{
|
||||||
|
isize += mSize;
|
||||||
|
|
||||||
|
for (int i = 0; i < mSize; i++)
|
||||||
|
{
|
||||||
|
if (mSeg[i] >= 0)
|
||||||
|
size += AsmInsModeSize[map.mIns[mSeg[i]].mMode];
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(size < 10000);
|
||||||
|
|
||||||
|
int cnt = 0;
|
||||||
|
for (int i = 0; i < HashSize; i++)
|
||||||
|
{
|
||||||
|
SuffixTree* t = mFirst[i];
|
||||||
|
while (t)
|
||||||
|
{
|
||||||
|
cnt += t->LongestMatch(map, size, isize, msize, mtree);
|
||||||
|
t = t->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size >= 6 && (size - 3) * (cnt - 1) > msize)
|
||||||
|
{
|
||||||
|
// Second run to cross check for overlaps
|
||||||
|
ExpandingArray<SuffixSegment> segs;
|
||||||
|
for (int i = 0; i < HashSize; i++)
|
||||||
|
{
|
||||||
|
SuffixTree* t = mFirst[i];
|
||||||
|
while (t)
|
||||||
|
{
|
||||||
|
t->CollectSuffix(map, 0, segs);
|
||||||
|
t = t->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
segs.Sort([](const SuffixSegment& l, const SuffixSegment& r)->bool {
|
||||||
|
return l.mBlock == r.mBlock ? l.mStart < r.mStart : ptrdiff_t(l.mBlock) < ptrdiff_t(r.mBlock);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (int i = 0; i + 1 < segs.Size(); i++)
|
||||||
|
{
|
||||||
|
if (segs[i].mBlock == segs[i + 1].mBlock && segs[i].mStart + isize > segs[i + 1].mStart)
|
||||||
|
cnt--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cnt > 1 && (size - 3) * (cnt - 1) > msize)
|
||||||
|
{
|
||||||
|
msize = (size - 3) * (cnt - 1);
|
||||||
|
mtree = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuffixTree::Print(FILE * file, NativeCodeMapper& map, int depth)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < depth; i++)
|
||||||
|
fprintf(file, ".");
|
||||||
|
|
||||||
|
for (int i = 0; i < mSize; i++)
|
||||||
|
{
|
||||||
|
fprintf(file, "[");
|
||||||
|
|
||||||
|
if (mSeg[i] >= 0)
|
||||||
|
map.mIns[mSeg[i]].Disassemble(file);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NativeCodeBasicBlock* block = map.mBlocks[- (mSeg[i] + 1)];
|
||||||
|
fprintf(file, "%s,%d", block->mProc->mInterProc->mIdent->mString, block->mIndex);
|
||||||
|
}
|
||||||
|
fprintf(file, "]");
|
||||||
|
}
|
||||||
|
fprintf(file, "\n");
|
||||||
|
|
||||||
|
if (mFirst)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < HashSize; i++)
|
||||||
|
{
|
||||||
|
SuffixTree* n = mFirst[i];
|
||||||
|
while (n)
|
||||||
|
{
|
||||||
|
n->Print(file, map, depth + 1);
|
||||||
|
n = n->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuffixTree::ParentPrint(FILE* file, NativeCodeMapper& map)
|
||||||
|
{
|
||||||
|
if (mParent)
|
||||||
|
mParent->ParentPrint(file, map);
|
||||||
|
for (int i = 0; i < mSize; i++)
|
||||||
|
{
|
||||||
|
if (mSeg[i] >= 0)
|
||||||
|
map.mIns[mSeg[i]].Disassemble(file);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NativeCodeBasicBlock* block = map.mBlocks[-(mSeg[i] + 1)];
|
||||||
|
fprintf(file, "%s,%d", block->mProc->mInterProc->mIdent->mString, block->mIndex);
|
||||||
|
}
|
||||||
|
fprintf(file, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int SuffixTree::ParentCodeSize(NativeCodeMapper& map) const
|
||||||
|
{
|
||||||
|
int size = 0;
|
||||||
|
for (int i = 0; i < mSize; i++)
|
||||||
|
{
|
||||||
|
if (mSeg[i] >= 0)
|
||||||
|
size += AsmInsModeSize[map.mIns[mSeg[i]].mMode];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mParent)
|
||||||
|
size += mParent->ParentCodeSize(map);
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuffixTree::ParentCollect(NativeCodeMapper& map, NativeCodeBasicBlock* block)
|
||||||
|
{
|
||||||
|
if (mParent)
|
||||||
|
mParent->ParentCollect(map, block);
|
||||||
|
for (int i = 0; i < mSize; i++)
|
||||||
|
block->mIns.Push(map.mIns[mSeg[i]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuffixTree::ReplaceCalls(NativeCodeMapper& map, ExpandingArray<SuffixSegment>& segs)
|
||||||
|
{
|
||||||
|
if (mFirst)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < HashSize; i++)
|
||||||
|
{
|
||||||
|
SuffixTree* n = mFirst[i];
|
||||||
|
while (n)
|
||||||
|
{
|
||||||
|
n->ChildReplaceCalls(map, this, 0, segs);
|
||||||
|
n = n->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuffixTree::ChildReplaceCalls(NativeCodeMapper& map, SuffixTree* tree, int offset, ExpandingArray<SuffixSegment>& segs)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mSize; i++)
|
||||||
|
{
|
||||||
|
if (mSeg[i] >= 0)
|
||||||
|
offset ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mFirst)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < HashSize; i++)
|
||||||
|
{
|
||||||
|
SuffixTree* n = mFirst[i];
|
||||||
|
while (n)
|
||||||
|
{
|
||||||
|
n->ChildReplaceCalls(map, tree, offset, segs);
|
||||||
|
n = n->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NativeCodeBasicBlock* block = map.mBlocks[-(mSeg[mSize - 1] + 1)];
|
||||||
|
tree->ParentReplaceCalls(map, block, offset, 0, segs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuffixTree::ParentReplaceCalls(NativeCodeMapper& map, NativeCodeBasicBlock* block, int offset, int size, ExpandingArray<SuffixSegment>& segs)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mSize; i++)
|
||||||
|
{
|
||||||
|
if (mSeg[i] >= 0)
|
||||||
|
size ++;
|
||||||
|
}
|
||||||
|
if (mParent)
|
||||||
|
mParent->ParentReplaceCalls(map, block, offset, size, segs);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int at = block->mIns.Size() - offset - size;
|
||||||
|
|
||||||
|
SuffixSegment seg;
|
||||||
|
seg.mBlock = block;
|
||||||
|
seg.mStart = at;
|
||||||
|
seg.mEnd = at + size;
|
||||||
|
segs.Push(seg);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "NativeCodeGenerator.h"
|
||||||
|
#include "Array.h"
|
||||||
|
|
||||||
|
class NativeCodeMapper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NativeCodeMapper(void);
|
||||||
|
~NativeCodeMapper(void);
|
||||||
|
|
||||||
|
void Reset(void);
|
||||||
|
|
||||||
|
int MapInstruction(const NativeCodeInstruction& ins, LinkerSection * ls);
|
||||||
|
int MapBasicBlock(NativeCodeBasicBlock* block);
|
||||||
|
|
||||||
|
ExpandingArray<NativeCodeInstruction> mIns;
|
||||||
|
ExpandingArray<NativeCodeBasicBlock*> mBlocks;
|
||||||
|
protected:
|
||||||
|
static const int HashSize = 256;
|
||||||
|
|
||||||
|
struct InsNode
|
||||||
|
{
|
||||||
|
int mIndex;
|
||||||
|
LinkerSection * mSection;
|
||||||
|
InsNode* mNext;
|
||||||
|
};
|
||||||
|
|
||||||
|
InsNode * mHash[HashSize];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SuffixSegment
|
||||||
|
{
|
||||||
|
NativeCodeBasicBlock * mBlock;
|
||||||
|
int mStart, mEnd;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SuffixTree
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const int * mSeg;
|
||||||
|
int mSize;
|
||||||
|
|
||||||
|
static const int HashSize = 32;
|
||||||
|
|
||||||
|
SuffixTree* mNext, * mParent, ** mFirst;
|
||||||
|
|
||||||
|
SuffixTree(const int* str, int s, SuffixTree* n);
|
||||||
|
~SuffixTree(void);
|
||||||
|
|
||||||
|
void AddParents(SuffixTree* parent);
|
||||||
|
|
||||||
|
void AddSuffix(const int* str, int s);
|
||||||
|
void AddString(const int* str);
|
||||||
|
|
||||||
|
void Print(FILE* file, NativeCodeMapper & map, int depth);
|
||||||
|
void ParentPrint(FILE* file, NativeCodeMapper& map);
|
||||||
|
int LongestMatch(NativeCodeMapper& map, int size, int isize, int & msize, SuffixTree *& mtree);
|
||||||
|
void CollectSuffix(NativeCodeMapper& map, int offset, ExpandingArray<SuffixSegment>& segs);
|
||||||
|
int ParentCodeSize(NativeCodeMapper& map) const;
|
||||||
|
void ParentCollect(NativeCodeMapper& map, NativeCodeBasicBlock * block);
|
||||||
|
void ReplaceCalls(NativeCodeMapper& map, ExpandingArray<SuffixSegment> & segs);
|
||||||
|
void ChildReplaceCalls(NativeCodeMapper& map, SuffixTree * tree, int offset, ExpandingArray<SuffixSegment>& segs);
|
||||||
|
void ParentReplaceCalls(NativeCodeMapper& map, NativeCodeBasicBlock* block, int offset, int size, ExpandingArray<SuffixSegment>& segs);
|
||||||
|
|
||||||
|
};
|
2180
oscar64/Parser.cpp
2180
oscar64/Parser.cpp
File diff suppressed because it is too large
Load Diff
|
@ -11,6 +11,7 @@ public:
|
||||||
~Parser(void);
|
~Parser(void);
|
||||||
|
|
||||||
Parser* Clone(void);
|
Parser* Clone(void);
|
||||||
|
Parser * mParent;
|
||||||
|
|
||||||
DeclarationScope * mGlobals, * mScope, * mTemplateScope, * mCaptureScope;
|
DeclarationScope * mGlobals, * mScope, * mTemplateScope, * mCaptureScope;
|
||||||
int mLocalIndex;
|
int mLocalIndex;
|
||||||
|
@ -24,6 +25,8 @@ public:
|
||||||
uint64 mCompilerOptionStack[32];
|
uint64 mCompilerOptionStack[32];
|
||||||
int mCompilerOptionSP;
|
int mCompilerOptionSP;
|
||||||
|
|
||||||
|
Location FullLocation(const Location& loc);
|
||||||
|
|
||||||
void Parse(void);
|
void Parse(void);
|
||||||
protected:
|
protected:
|
||||||
bool ExpectToken(Token token);
|
bool ExpectToken(Token token);
|
||||||
|
@ -77,12 +80,13 @@ protected:
|
||||||
Expression* DefaultInitExpression(Expression* vexp);
|
Expression* DefaultInitExpression(Expression* vexp);
|
||||||
Expression* ParseVarInitExpression(Expression* lexp, bool inner = false);
|
Expression* ParseVarInitExpression(Expression* lexp, bool inner = false);
|
||||||
Expression* CloneVarInitExpression(Expression* vexp, Expression* iexp, Expression * qexp);
|
Expression* CloneVarInitExpression(Expression* vexp, Expression* iexp, Expression * qexp);
|
||||||
|
Expression* CopyElision(Expression* vexp, Expression* rexp);
|
||||||
|
|
||||||
Declaration* ParsePostfixDeclaration(void);
|
Declaration* ParsePostfixDeclaration(void);
|
||||||
Declaration* ReverseDeclaration(Declaration* odec, Declaration* bdec);
|
Declaration* ReverseDeclaration(Declaration* odec, Declaration* bdec);
|
||||||
|
|
||||||
Expression* ParseFunction(Declaration* dec);
|
Expression* ParseFunction(Declaration* dec);
|
||||||
Expression* ParseAssembler(void);
|
Expression* ParseAssembler(Declaration * vdassm = nullptr);
|
||||||
|
|
||||||
Expression* ParseAssemblerBaseOperand(Declaration* pcasm, int pcoffset);
|
Expression* ParseAssemblerBaseOperand(Declaration* pcasm, int pcoffset);
|
||||||
Expression* ParseAssemblerMulOperand(Declaration* pcasm, int pcoffset);
|
Expression* ParseAssemblerMulOperand(Declaration* pcasm, int pcoffset);
|
||||||
|
@ -133,7 +137,10 @@ protected:
|
||||||
|
|
||||||
Declaration* ParseTypeID(bool tid, Declaration * bdec = nullptr);
|
Declaration* ParseTypeID(bool tid, Declaration * bdec = nullptr);
|
||||||
|
|
||||||
|
Expression* ParseConstruction(Declaration* type);
|
||||||
|
|
||||||
Expression* ParseCastExpression(Expression* exp);
|
Expression* ParseCastExpression(Expression* exp);
|
||||||
|
Expression* ParseIdentExpression(const Location & eloc, Declaration* dec, bool lhs, bool tid = false);
|
||||||
Expression* ParseSimpleExpression(bool lhs, bool tid = false);
|
Expression* ParseSimpleExpression(bool lhs, bool tid = false);
|
||||||
Expression* ParsePrefixExpression(bool lhs);
|
Expression* ParsePrefixExpression(bool lhs);
|
||||||
Expression* ParsePostfixExpression(bool lhs);
|
Expression* ParsePostfixExpression(bool lhs);
|
||||||
|
@ -152,9 +159,10 @@ protected:
|
||||||
Expression* ParseRExpression(void);
|
Expression* ParseRExpression(void);
|
||||||
|
|
||||||
Expression* ExpandArgumentPack(Expression * exp, Declaration* dec);
|
Expression* ExpandArgumentPack(Expression * exp, Declaration* dec);
|
||||||
Expression* ParseListExpression(bool lhs);
|
Expression* ParseListExpression(bool lhs, Declaration * params = nullptr);
|
||||||
|
|
||||||
Expression* ParseParenthesisExpression(void);
|
Expression* ParseParenthesisExpression(void);
|
||||||
|
void ParseStaticAssert(void);
|
||||||
|
|
||||||
Errors* mErrors;
|
Errors* mErrors;
|
||||||
Scanner* mScanner;
|
Scanner* mScanner;
|
||||||
|
|
|
@ -44,7 +44,7 @@ bool SourceFile::ReadLineLZO(char* line, ptrdiff_t limit)
|
||||||
while (pi < 127 && mPos < mFill)
|
while (pi < 127 && mPos < mFill)
|
||||||
{
|
{
|
||||||
int bi = pi, bj = 0;
|
int bi = pi, bj = 0;
|
||||||
for (int i = 1; i < mPos; i++)
|
for (int i = 1; i <= (mPos < 255 ? mPos : 255); i++)
|
||||||
{
|
{
|
||||||
int j = 0;
|
int j = 0;
|
||||||
while (j < 127 && mPos + j < mFill && mBuffer[mPos - i + j] == mBuffer[mPos + j])
|
while (j < 127 && mPos + j < mFill && mBuffer[mPos - i + j] == mBuffer[mPos + j])
|
||||||
|
@ -327,6 +327,16 @@ struct CTMHeader9
|
||||||
uint8 mColors[7];
|
uint8 mColors[7];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CTTHeader9
|
||||||
|
{
|
||||||
|
uint8 mDispMode;
|
||||||
|
uint8 mColorMethod;
|
||||||
|
uint8 mFlags;
|
||||||
|
uint8 mFgridWidth[2], mFGridHeight[2];
|
||||||
|
char mFGridConfig;
|
||||||
|
uint8 mColors[6];
|
||||||
|
};
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct SPDHeader5
|
struct SPDHeader5
|
||||||
|
@ -486,6 +496,7 @@ void SourceFile::ReadCharPad(Errors* errors, const Location& location, SourceFil
|
||||||
CTMHeader ctmHeader;
|
CTMHeader ctmHeader;
|
||||||
CTMHeader8 ctmHeader8;
|
CTMHeader8 ctmHeader8;
|
||||||
CTMHeader9 ctmHeader9;
|
CTMHeader9 ctmHeader9;
|
||||||
|
CTTHeader9 cttHeader9;
|
||||||
uint16 ctmMarker, numChars, numTiles;
|
uint16 ctmMarker, numChars, numTiles;
|
||||||
char tileWidth, tileHeight;
|
char tileWidth, tileHeight;
|
||||||
|
|
||||||
|
@ -496,10 +507,20 @@ void SourceFile::ReadCharPad(Errors* errors, const Location& location, SourceFil
|
||||||
fread(&ctmHeader8, sizeof(CTMHeader8), 1, mFile);
|
fread(&ctmHeader8, sizeof(CTMHeader8), 1, mFile);
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
|
if (ctmHeader.mID[2] == 'T')
|
||||||
|
{
|
||||||
|
fread(&cttHeader9, sizeof(CTTHeader9), 1, mFile);
|
||||||
|
ctmHeader8.mDispMode = cttHeader9.mDispMode;
|
||||||
|
ctmHeader8.mColorMethod = cttHeader9.mColorMethod;
|
||||||
|
ctmHeader8.mFlags = cttHeader9.mFlags;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
fread(&ctmHeader9, sizeof(CTMHeader9), 1, mFile);
|
fread(&ctmHeader9, sizeof(CTMHeader9), 1, mFile);
|
||||||
ctmHeader8.mDispMode = ctmHeader9.mDispMode;
|
ctmHeader8.mDispMode = ctmHeader9.mDispMode;
|
||||||
ctmHeader8.mColorMethod = ctmHeader9.mColorMethod;
|
ctmHeader8.mColorMethod = ctmHeader9.mColorMethod;
|
||||||
ctmHeader8.mFlags = ctmHeader9.mFlags;
|
ctmHeader8.mFlags = ctmHeader9.mFlags;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,7 @@ const char* TokenNames[] =
|
||||||
"'extern'",
|
"'extern'",
|
||||||
"'inline'",
|
"'inline'",
|
||||||
"'__assume'",
|
"'__assume'",
|
||||||
|
"'static_assert'",
|
||||||
|
|
||||||
"__asm",
|
"__asm",
|
||||||
"__interrupt",
|
"__interrupt",
|
||||||
|
@ -173,6 +174,7 @@ const char* TokenNames[] =
|
||||||
"'friend'",
|
"'friend'",
|
||||||
"'constexpr'",
|
"'constexpr'",
|
||||||
"'typename'",
|
"'typename'",
|
||||||
|
"'decltype'",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -355,7 +357,7 @@ Scanner::Scanner(Errors* errors, Preprocessor* preprocessor)
|
||||||
mToken = TK_NONE;
|
mToken = TK_NONE;
|
||||||
mUngetToken = TK_NONE;
|
mUngetToken = TK_NONE;
|
||||||
mReplay = nullptr;
|
mReplay = nullptr;
|
||||||
mRecord = mRecordLast = nullptr;
|
mRecord = mRecordLast = mRecordPrev = nullptr;
|
||||||
|
|
||||||
mOnceDict = new MacroDict();
|
mOnceDict = new MacroDict();
|
||||||
|
|
||||||
|
@ -372,13 +374,13 @@ Scanner::~Scanner(void)
|
||||||
|
|
||||||
void Scanner::BeginRecord(void)
|
void Scanner::BeginRecord(void)
|
||||||
{
|
{
|
||||||
mRecord = mRecordLast = new TokenSequence(this);
|
mRecord = mRecordLast = mRecordPrev = new TokenSequence(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
TokenSequence* Scanner::CompleteRecord(void)
|
TokenSequence* Scanner::CompleteRecord(void)
|
||||||
{
|
{
|
||||||
TokenSequence* seq = mRecord;
|
TokenSequence* seq = mRecord;
|
||||||
mRecord = mRecordLast = nullptr;
|
mRecord = mRecordLast = mRecordPrev = nullptr;
|
||||||
return seq;
|
return seq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,6 +485,8 @@ void Scanner::UngetToken(Token token)
|
||||||
{
|
{
|
||||||
mUngetToken = mToken;
|
mUngetToken = mToken;
|
||||||
mToken = token;
|
mToken = token;
|
||||||
|
if (mRecord)
|
||||||
|
mRecordLast = mRecordPrev;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scanner::NextToken(void)
|
void Scanner::NextToken(void)
|
||||||
|
@ -491,10 +495,8 @@ void Scanner::NextToken(void)
|
||||||
{
|
{
|
||||||
mToken = mUngetToken;
|
mToken = mUngetToken;
|
||||||
mUngetToken = TK_NONE;
|
mUngetToken = TK_NONE;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else if (mReplay)
|
||||||
if (mReplay)
|
|
||||||
{
|
{
|
||||||
mLocation = mReplay->mLocation;
|
mLocation = mReplay->mLocation;
|
||||||
mToken = mReplay->mToken;
|
mToken = mReplay->mToken;
|
||||||
|
@ -515,6 +517,7 @@ void Scanner::NextToken(void)
|
||||||
|
|
||||||
if (mRecord)
|
if (mRecord)
|
||||||
{
|
{
|
||||||
|
mRecordPrev = mRecordLast;
|
||||||
mRecordLast->mNext = new TokenSequence(this);
|
mRecordLast->mNext = new TokenSequence(this);
|
||||||
mRecordLast = mRecordLast->mNext;
|
mRecordLast = mRecordLast->mNext;
|
||||||
}
|
}
|
||||||
|
@ -819,6 +822,8 @@ void Scanner::NextPreToken(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mToken == TK_PREP_IDENT)
|
else if (mToken == TK_PREP_IDENT)
|
||||||
|
{
|
||||||
|
if (mTokenIdent->mString[0])
|
||||||
{
|
{
|
||||||
Macro* def = nullptr;
|
Macro* def = nullptr;
|
||||||
if (mDefineArguments)
|
if (mDefineArguments)
|
||||||
|
@ -843,6 +848,12 @@ void Scanner::NextPreToken(void)
|
||||||
else
|
else
|
||||||
mErrors->Error(mLocation, EERR_INVALID_PREPROCESSOR, "Invalid preprocessor command", mTokenIdent);
|
mErrors->Error(mLocation, EERR_INVALID_PREPROCESSOR, "Invalid preprocessor command", mTokenIdent);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mToken = TK_HASH;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (mToken == TK_PREP_UNDEF)
|
else if (mToken == TK_PREP_UNDEF)
|
||||||
{
|
{
|
||||||
NextRawToken();
|
NextRawToken();
|
||||||
|
@ -1114,14 +1125,15 @@ void Scanner::NextPreToken(void)
|
||||||
while (mTokenChar == ' ')
|
while (mTokenChar == ' ')
|
||||||
NextChar();
|
NextChar();
|
||||||
|
|
||||||
while (mTokenChar == '#' && mLine[mOffset] == '#')
|
if (mTokenChar == '#' && mLine[mOffset] == '#')
|
||||||
{
|
{
|
||||||
mOffset++;
|
|
||||||
NextChar();
|
|
||||||
|
|
||||||
char tkbase[256];
|
char tkbase[256];
|
||||||
strcpy_s(tkbase, mTokenIdent->mString);
|
strcpy_s(tkbase, mTokenIdent->mString);
|
||||||
|
|
||||||
|
do {
|
||||||
|
mOffset++;
|
||||||
|
NextChar();
|
||||||
|
|
||||||
ptrdiff_t n = 0;
|
ptrdiff_t n = 0;
|
||||||
char tkident[256];
|
char tkident[256];
|
||||||
while (IsIdentChar(mTokenChar))
|
while (IsIdentChar(mTokenChar))
|
||||||
|
@ -1150,9 +1162,32 @@ void Scanner::NextPreToken(void)
|
||||||
n--;
|
n--;
|
||||||
tkbase[n] = 0;
|
tkbase[n] = 0;
|
||||||
|
|
||||||
mTokenIdent = Ident::Unique(tkbase);
|
while (mTokenChar == ' ')
|
||||||
}
|
NextChar();
|
||||||
|
|
||||||
|
} while (mTokenChar == '#' && mLine[mOffset] == '#');
|
||||||
|
|
||||||
|
ptrdiff_t n = strlen(tkbase);
|
||||||
|
char* str = new char[n + 1];
|
||||||
|
strcpy_s(str, n + 1, tkbase);
|
||||||
|
|
||||||
|
MacroExpansion* ex = new MacroExpansion();
|
||||||
|
ex->mDefinedArguments = mDefineArguments;
|
||||||
|
|
||||||
|
ex->mLine = mLine;
|
||||||
|
ex->mOffset = mOffset;
|
||||||
|
ex->mLink = mMacroExpansion;
|
||||||
|
ex->mChar = mTokenChar;
|
||||||
|
|
||||||
|
mMacroExpansion = ex;
|
||||||
|
mMacroExpansionDepth++;
|
||||||
|
if (mMacroExpansionDepth > 1024)
|
||||||
|
mErrors->Error(mLocation, EFATAL_MACRO_EXPANSION_DEPTH, "Maximum macro expansion depth exceeded", mTokenIdent);
|
||||||
|
mLine = str;
|
||||||
|
mOffset = 0;
|
||||||
|
NextChar();
|
||||||
|
}
|
||||||
|
else
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1798,6 +1833,8 @@ void Scanner::NextRawToken(void)
|
||||||
mToken = TK_ASM;
|
mToken = TK_ASM;
|
||||||
else if (!strcmp(tkident, "__assume"))
|
else if (!strcmp(tkident, "__assume"))
|
||||||
mToken = TK_ASSUME;
|
mToken = TK_ASSUME;
|
||||||
|
else if (!strcmp(tkident, "static_assert"))
|
||||||
|
mToken = TK_STATIC_ASSERT;
|
||||||
else if (!strcmp(tkident, "__interrupt"))
|
else if (!strcmp(tkident, "__interrupt"))
|
||||||
mToken = TK_INTERRUPT;
|
mToken = TK_INTERRUPT;
|
||||||
else if (!strcmp(tkident, "__hwinterrupt"))
|
else if (!strcmp(tkident, "__hwinterrupt"))
|
||||||
|
@ -1846,6 +1883,8 @@ void Scanner::NextRawToken(void)
|
||||||
mToken = TK_CONSTEXPR;
|
mToken = TK_CONSTEXPR;
|
||||||
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "typename"))
|
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "typename"))
|
||||||
mToken = TK_TYPENAME;
|
mToken = TK_TYPENAME;
|
||||||
|
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "decltype"))
|
||||||
|
mToken = TK_DECLTYPE;
|
||||||
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator"))
|
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator"))
|
||||||
{
|
{
|
||||||
NextRawToken();
|
NextRawToken();
|
||||||
|
@ -1975,7 +2014,7 @@ void Scanner::NextRawToken(void)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// dirty little hack to implement token preview, got to fix
|
// dirty little hack to implement token preview, got to fix
|
||||||
// this with an infinit preview sequence at one point
|
// this with an infinite preview sequence at one point
|
||||||
mUngetToken = mToken;
|
mUngetToken = mToken;
|
||||||
mToken = TK_OPERATOR;
|
mToken = TK_OPERATOR;
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -49,6 +49,7 @@ enum Token
|
||||||
TK_EXTERN,
|
TK_EXTERN,
|
||||||
TK_INLINE,
|
TK_INLINE,
|
||||||
TK_ASSUME,
|
TK_ASSUME,
|
||||||
|
TK_STATIC_ASSERT,
|
||||||
|
|
||||||
TK_ASM,
|
TK_ASM,
|
||||||
TK_INTERRUPT,
|
TK_INTERRUPT,
|
||||||
|
@ -172,6 +173,7 @@ enum Token
|
||||||
TK_FRIEND,
|
TK_FRIEND,
|
||||||
TK_CONSTEXPR,
|
TK_CONSTEXPR,
|
||||||
TK_TYPENAME,
|
TK_TYPENAME,
|
||||||
|
TK_DECLTYPE,
|
||||||
|
|
||||||
NUM_TOKENS
|
NUM_TOKENS
|
||||||
};
|
};
|
||||||
|
@ -315,7 +317,7 @@ protected:
|
||||||
Token mUngetToken;
|
Token mUngetToken;
|
||||||
|
|
||||||
const TokenSequence* mReplay;
|
const TokenSequence* mReplay;
|
||||||
TokenSequence* mRecord, * mRecordLast;
|
TokenSequence* mRecord, * mRecordLast, * mRecordPrev;
|
||||||
|
|
||||||
void StringToken(char terminator, char mode);
|
void StringToken(char terminator, char mode);
|
||||||
void CharToken(char mode);
|
void CharToken(char mode);
|
||||||
|
|
|
@ -76,7 +76,7 @@ int main2(int argc, const char** argv)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
strcpy(strProductName, "oscar64");
|
strcpy(strProductName, "oscar64");
|
||||||
strcpy(strProductVersion, "1.31.257");
|
strcpy(strProductVersion, "1.31.261");
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
uint32_t length = sizeof(basePath);
|
uint32_t length = sizeof(basePath);
|
||||||
|
@ -111,38 +111,12 @@ int main2(int argc, const char** argv)
|
||||||
GrowingArray<const char*> dataFiles(nullptr);
|
GrowingArray<const char*> dataFiles(nullptr);
|
||||||
GrowingArray<bool> dataFileCompressed(false);
|
GrowingArray<bool> dataFileCompressed(false);
|
||||||
|
|
||||||
|
bool emulate = false, profile = false, customCRT = false;
|
||||||
|
int trace = 0;
|
||||||
|
|
||||||
compiler->mPreprocessor->AddPath(basePath);
|
compiler->mPreprocessor->AddPath(basePath);
|
||||||
strcpy_s(includePath, basePath);
|
strcpy_s(includePath, basePath);
|
||||||
{
|
strcat_s(includePath, "include");
|
||||||
FILE* crtFile;
|
|
||||||
char crtFileNamePath[FILENAME_MAX];
|
|
||||||
crtFileNamePath[FILENAME_MAX - 1] = '\0';
|
|
||||||
strcpy_s(crtFileNamePath, basePath);
|
|
||||||
strcat_s(crtFileNamePath, "include/crt.h");
|
|
||||||
|
|
||||||
if (!fopen_s(&crtFile, crtFileNamePath, "r"))
|
|
||||||
strcat_s(includePath, "include/");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
strcpy_s(crtFileNamePath, basePath);
|
|
||||||
strcat_s(crtFileNamePath, "include/oscar64/crt.h");
|
|
||||||
|
|
||||||
if (!fopen_s(&crtFile, crtFileNamePath, "r"))
|
|
||||||
strcat_s(includePath, "include/oscar64/");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("Could not locate Oscar64 includes under %s\n", basePath);
|
|
||||||
return 20;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(crtFile);
|
|
||||||
}
|
|
||||||
compiler->mPreprocessor->AddPath(includePath);
|
|
||||||
strcpy_s(crtPath, includePath);
|
|
||||||
strcat_s(crtPath, "crt.c");
|
|
||||||
|
|
||||||
bool emulate = false, profile = false;
|
|
||||||
int trace = 0;
|
|
||||||
|
|
||||||
targetPath[0] = 0;
|
targetPath[0] = 0;
|
||||||
diskPath[0] = 0;
|
diskPath[0] = 0;
|
||||||
|
@ -185,6 +159,10 @@ int main2(int argc, const char** argv)
|
||||||
{
|
{
|
||||||
compiler->mPreprocessor->AddPath(arg + 3);
|
compiler->mPreprocessor->AddPath(arg + 3);
|
||||||
}
|
}
|
||||||
|
else if (arg[1] == 'i' && arg[2] == 'i' && arg[3] == '=')
|
||||||
|
{
|
||||||
|
strcpy_s(includePath, arg + 4);
|
||||||
|
}
|
||||||
else if (arg[1] == 'f' && arg[2] == '=')
|
else if (arg[1] == 'f' && arg[2] == '=')
|
||||||
{
|
{
|
||||||
dataFiles.Push(arg + 3);
|
dataFiles.Push(arg + 3);
|
||||||
|
@ -206,6 +184,7 @@ int main2(int argc, const char** argv)
|
||||||
else if (arg[1] == 'r' && arg[2] == 't' && arg[3] == '=')
|
else if (arg[1] == 'r' && arg[2] == 't' && arg[3] == '=')
|
||||||
{
|
{
|
||||||
strcpy_s(crtPath, arg + 4);
|
strcpy_s(crtPath, arg + 4);
|
||||||
|
customCRT = true;
|
||||||
}
|
}
|
||||||
else if (arg[1] == 'd' && arg[2] == '6' && arg[3] == '4' && arg[4] == '=')
|
else if (arg[1] == 'd' && arg[2] == '6' && arg[3] == '4' && arg[4] == '=')
|
||||||
{
|
{
|
||||||
|
@ -253,6 +232,8 @@ int main2(int argc, const char** argv)
|
||||||
compiler->mCompilerOptions |= COPT_OPTIMIZE_ASSEMBLER;
|
compiler->mCompilerOptions |= COPT_OPTIMIZE_ASSEMBLER;
|
||||||
else if (arg[2] == 'i' && !arg[3])
|
else if (arg[2] == 'i' && !arg[3])
|
||||||
compiler->mCompilerOptions |= COPT_OPTIMIZE_AUTO_INLINE;
|
compiler->mCompilerOptions |= COPT_OPTIMIZE_AUTO_INLINE;
|
||||||
|
else if (arg[2] == 'i' && arg[3] == 'i' && !arg[4])
|
||||||
|
compiler->mCompilerOptions |= COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_INLINE_ALL;
|
||||||
else if (arg[2] == 'z' && !arg[3])
|
else if (arg[2] == 'z' && !arg[3])
|
||||||
compiler->mCompilerOptions |= COPT_OPTIMIZE_AUTO_ZEROPAGE;
|
compiler->mCompilerOptions |= COPT_OPTIMIZE_AUTO_ZEROPAGE;
|
||||||
else if (arg[2] == 'p' && !arg[3])
|
else if (arg[2] == 'p' && !arg[3])
|
||||||
|
@ -261,6 +242,10 @@ int main2(int argc, const char** argv)
|
||||||
compiler->mCompilerOptions |= COPT_OPTIMIZE_GLOBAL;
|
compiler->mCompilerOptions |= COPT_OPTIMIZE_GLOBAL;
|
||||||
else if (arg[2] == 'm' && !arg[3])
|
else if (arg[2] == 'm' && !arg[3])
|
||||||
compiler->mCompilerOptions |= COPT_OPTIMIZE_MERGE_CALLS;
|
compiler->mCompilerOptions |= COPT_OPTIMIZE_MERGE_CALLS;
|
||||||
|
else if (arg[2] == 'o' && !arg[3])
|
||||||
|
compiler->mCompilerOptions |= COPT_OPTIMIZE_OUTLINE;
|
||||||
|
else if (arg[2] == 'x' && !arg[3])
|
||||||
|
compiler->mCompilerOptions |= COPT_OPTIMIZE_PAGE_CROSSING;
|
||||||
else
|
else
|
||||||
compiler->mErrors->Error(loc, EERR_COMMAND_LINE, "Invalid command line argument", arg);
|
compiler->mErrors->Error(loc, EERR_COMMAND_LINE, "Invalid command line argument", arg);
|
||||||
}
|
}
|
||||||
|
@ -321,6 +306,12 @@ int main2(int argc, const char** argv)
|
||||||
{
|
{
|
||||||
compiler->mCompilerOptions |= COPT_CPLUSPLUS;
|
compiler->mCompilerOptions |= COPT_CPLUSPLUS;
|
||||||
compiler->AddDefine(Ident::Unique("__cplusplus"), "1");
|
compiler->AddDefine(Ident::Unique("__cplusplus"), "1");
|
||||||
|
compiler->AddDefine(Ident::Unique("__cplusplus__"), "1");
|
||||||
|
}
|
||||||
|
else if (arg[1] == 's' && arg[2] == 't' && arg[3] == 'r' && arg[4] == 'i' && arg[5] == 'c' && arg[6] == 't' && !arg[7])
|
||||||
|
{
|
||||||
|
compiler->mCompilerOptions |= COPT_STRICT;
|
||||||
|
compiler->AddDefine(Ident::Unique("__strict__"), "1");
|
||||||
}
|
}
|
||||||
else if (arg[1] == 'r' && arg[2] == 'm' && arg[3] == 'p' && !arg[4])
|
else if (arg[1] == 'r' && arg[2] == 'm' && arg[3] == 'p' && !arg[4])
|
||||||
{
|
{
|
||||||
|
@ -339,6 +330,7 @@ int main2(int argc, const char** argv)
|
||||||
{
|
{
|
||||||
compiler->mCompilerOptions |= COPT_CPLUSPLUS;
|
compiler->mCompilerOptions |= COPT_CPLUSPLUS;
|
||||||
compiler->AddDefine(Ident::Unique("__cplusplus"), "1");
|
compiler->AddDefine(Ident::Unique("__cplusplus"), "1");
|
||||||
|
compiler->AddDefine(Ident::Unique("__cplusplus__"), "1");
|
||||||
}
|
}
|
||||||
|
|
||||||
compiler->mCompilationUnits->AddUnit(loc, argv[i], nullptr);
|
compiler->mCompilationUnits->AddUnit(loc, argv[i], nullptr);
|
||||||
|
@ -435,6 +427,12 @@ int main2(int argc, const char** argv)
|
||||||
compiler->mTargetMachine = TMACH_PLUS4;
|
compiler->mTargetMachine = TMACH_PLUS4;
|
||||||
compiler->AddDefine(Ident::Unique("__PLUS4__"), "1");
|
compiler->AddDefine(Ident::Unique("__PLUS4__"), "1");
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(targetMachine, "mega65"))
|
||||||
|
{
|
||||||
|
strcpy_s(basicStart, "0x2001");
|
||||||
|
compiler->mTargetMachine = TMACH_MEGA65;
|
||||||
|
compiler->AddDefine(Ident::Unique("__MEGA65__"), "1");
|
||||||
|
}
|
||||||
else if (!strcmp(targetMachine, "x16"))
|
else if (!strcmp(targetMachine, "x16"))
|
||||||
{
|
{
|
||||||
strcpy_s(basicStart, "0x0801");
|
strcpy_s(basicStart, "0x0801");
|
||||||
|
@ -559,6 +557,35 @@ int main2(int argc, const char** argv)
|
||||||
|
|
||||||
// Add runtime module
|
// Add runtime module
|
||||||
|
|
||||||
|
compiler->mPreprocessor->AddPath(includePath);
|
||||||
|
|
||||||
|
if (!customCRT)
|
||||||
|
{
|
||||||
|
FILE* crtFile;
|
||||||
|
char crtFileNamePath[FILENAME_MAX];
|
||||||
|
crtFileNamePath[FILENAME_MAX - 1] = '\0';
|
||||||
|
strcpy_s(crtFileNamePath, includePath);
|
||||||
|
strcat_s(crtFileNamePath, "/crt.h");
|
||||||
|
|
||||||
|
if (fopen_s(&crtFile, crtFileNamePath, "r"))
|
||||||
|
{
|
||||||
|
strcpy_s(crtFileNamePath, basePath);
|
||||||
|
strcat_s(crtFileNamePath, "include/oscar64/crt.h");
|
||||||
|
|
||||||
|
if (!fopen_s(&crtFile, crtFileNamePath, "r"))
|
||||||
|
strcat_s(includePath, "include/oscar64/");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Could not locate Oscar64 includes under %s\n", basePath);
|
||||||
|
return 20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(crtFile);
|
||||||
|
|
||||||
|
strcpy_s(crtPath, includePath);
|
||||||
|
strcat_s(crtPath, "/crt.c");
|
||||||
|
}
|
||||||
|
|
||||||
if (crtPath[0])
|
if (crtPath[0])
|
||||||
compiler->mCompilationUnits->AddUnit(loc, crtPath, nullptr);
|
compiler->mCompilationUnits->AddUnit(loc, crtPath, nullptr);
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 1,31,257,0
|
FILEVERSION 1,31,261,0
|
||||||
PRODUCTVERSION 1,31,257,0
|
PRODUCTVERSION 1,31,261,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -43,12 +43,12 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "oscar64"
|
VALUE "CompanyName", "oscar64"
|
||||||
VALUE "FileDescription", "oscar64 compiler"
|
VALUE "FileDescription", "oscar64 compiler"
|
||||||
VALUE "FileVersion", "1.31.257.0"
|
VALUE "FileVersion", "1.31.261.0"
|
||||||
VALUE "InternalName", "oscar64.exe"
|
VALUE "InternalName", "oscar64.exe"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2021"
|
VALUE "LegalCopyright", "Copyright (C) 2021"
|
||||||
VALUE "OriginalFilename", "oscar64.exe"
|
VALUE "OriginalFilename", "oscar64.exe"
|
||||||
VALUE "ProductName", "oscar64"
|
VALUE "ProductName", "oscar64"
|
||||||
VALUE "ProductVersion", "1.31.257.0"
|
VALUE "ProductVersion", "1.31.261.0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
@ -189,6 +189,7 @@
|
||||||
<ClCompile Include="Linker.cpp" />
|
<ClCompile Include="Linker.cpp" />
|
||||||
<ClCompile Include="MachineTypes.cpp" />
|
<ClCompile Include="MachineTypes.cpp" />
|
||||||
<ClCompile Include="NativeCodeGenerator.cpp" />
|
<ClCompile Include="NativeCodeGenerator.cpp" />
|
||||||
|
<ClCompile Include="NativeCodeOutliner.cpp" />
|
||||||
<ClCompile Include="NumberSet.cpp" />
|
<ClCompile Include="NumberSet.cpp" />
|
||||||
<ClCompile Include="oscar64.cpp" />
|
<ClCompile Include="oscar64.cpp" />
|
||||||
<ClCompile Include="Parser.cpp" />
|
<ClCompile Include="Parser.cpp" />
|
||||||
|
@ -218,6 +219,7 @@
|
||||||
<ClInclude Include="Linker.h" />
|
<ClInclude Include="Linker.h" />
|
||||||
<ClInclude Include="MachineTypes.h" />
|
<ClInclude Include="MachineTypes.h" />
|
||||||
<ClInclude Include="NativeCodeGenerator.h" />
|
<ClInclude Include="NativeCodeGenerator.h" />
|
||||||
|
<ClInclude Include="NativeCodeOutliner.h" />
|
||||||
<ClInclude Include="NumberSet.h" />
|
<ClInclude Include="NumberSet.h" />
|
||||||
<ClInclude Include="Parser.h" />
|
<ClInclude Include="Parser.h" />
|
||||||
<ClInclude Include="Preprocessor.h" />
|
<ClInclude Include="Preprocessor.h" />
|
||||||
|
|
|
@ -87,6 +87,9 @@
|
||||||
<ClCompile Include="Compression.cpp">
|
<ClCompile Include="Compression.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="NativeCodeOutliner.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Array.h">
|
<ClInclude Include="Array.h">
|
||||||
|
@ -170,6 +173,9 @@
|
||||||
<ClInclude Include="Compression.h">
|
<ClInclude Include="Compression.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="NativeCodeOutliner.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="oscar64.rc">
|
<ResourceCompile Include="oscar64.rc">
|
||||||
|
|
|
@ -6310,15 +6310,15 @@
|
||||||
{
|
{
|
||||||
"Name" = "8:Microsoft Visual Studio"
|
"Name" = "8:Microsoft Visual Studio"
|
||||||
"ProductName" = "8:oscar64"
|
"ProductName" = "8:oscar64"
|
||||||
"ProductCode" = "8:{6792319A-5F61-4488-AF65-0F772832E2AC}"
|
"ProductCode" = "8:{1B9A0E10-DEA6-4276-AC91-17782FE44D94}"
|
||||||
"PackageCode" = "8:{2E154137-8761-471C-A56E-D8F5BED781E5}"
|
"PackageCode" = "8:{51BFE576-50D1-4F8F-AE7A-9FF07396F53D}"
|
||||||
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
|
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
|
||||||
"AspNetVersion" = "8:2.0.50727.0"
|
"AspNetVersion" = "8:2.0.50727.0"
|
||||||
"RestartWWWService" = "11:FALSE"
|
"RestartWWWService" = "11:FALSE"
|
||||||
"RemovePreviousVersions" = "11:TRUE"
|
"RemovePreviousVersions" = "11:TRUE"
|
||||||
"DetectNewerInstalledVersion" = "11:TRUE"
|
"DetectNewerInstalledVersion" = "11:TRUE"
|
||||||
"InstallAllUsers" = "11:FALSE"
|
"InstallAllUsers" = "11:FALSE"
|
||||||
"ProductVersion" = "8:1.31.257"
|
"ProductVersion" = "8:1.31.261"
|
||||||
"Manufacturer" = "8:oscar64"
|
"Manufacturer" = "8:oscar64"
|
||||||
"ARPHELPTELEPHONE" = "8:"
|
"ARPHELPTELEPHONE" = "8:"
|
||||||
"ARPHELPLINK" = "8:"
|
"ARPHELPLINK" = "8:"
|
||||||
|
|
|
@ -29,7 +29,7 @@ const char MissileChars[] = {
|
||||||
#define Charset ((char *)0xd800)
|
#define Charset ((char *)0xd800)
|
||||||
|
|
||||||
// Joystick and crosshair control
|
// Joystick and crosshair control
|
||||||
int CrossX = 160, CrossY = 100;
|
volatile int CrossX = 160, CrossY = 100;
|
||||||
bool CrossP = false;
|
bool CrossP = false;
|
||||||
char CrossDelay = 0;
|
char CrossDelay = 0;
|
||||||
|
|
||||||
|
@ -553,20 +553,22 @@ __interrupt void joy_interrupt()
|
||||||
joy_poll(0);
|
joy_poll(0);
|
||||||
|
|
||||||
// Move crosshair coordinates
|
// Move crosshair coordinates
|
||||||
CrossX += 2 * joyx[0]; CrossY += 2 * joyy[0];
|
int cx = CrossX + 2 * joyx[0], cy = CrossY + 2 * joyy[0];
|
||||||
|
|
||||||
// Stop at edges of screen
|
// Stop at edges of screen
|
||||||
if (CrossX < 8)
|
if (cx < 8)
|
||||||
CrossX = 8;
|
cx = 8;
|
||||||
else if (CrossX > 312)
|
else if (cx > 312)
|
||||||
CrossX = 312;
|
cx = 312;
|
||||||
if (CrossY < 20)
|
if (cy < 20)
|
||||||
CrossY = 20;
|
cy = 20;
|
||||||
else if (CrossY > 172)
|
else if (cy > 172)
|
||||||
CrossY = 172;
|
cy = 172;
|
||||||
|
|
||||||
// Move crosshair sprite
|
// Move crosshair sprite
|
||||||
spr_move(0, CrossX + 14, CrossY + 40);
|
spr_move(0, cx + 14, cy + 40);
|
||||||
|
CrossX = cx;
|
||||||
|
CrossY = cy;
|
||||||
|
|
||||||
// Check button
|
// Check button
|
||||||
if (joyb[0])
|
if (joyb[0])
|
||||||
|
@ -697,15 +699,17 @@ void game_play(void)
|
||||||
// Check if fire request
|
// Check if fire request
|
||||||
if (CrossP)
|
if (CrossP)
|
||||||
{
|
{
|
||||||
|
int cx = CrossX, cy = CrossY;
|
||||||
|
|
||||||
// Find launch site
|
// Find launch site
|
||||||
int sx = 160;
|
int sx = 160;
|
||||||
if (CrossX < 120)
|
if (cx < 120)
|
||||||
sx = 24;
|
sx = 24;
|
||||||
else if (CrossX > 200)
|
else if (cx > 200)
|
||||||
sx = 296;
|
sx = 296;
|
||||||
|
|
||||||
// Fire missile
|
// Fire missile
|
||||||
missile_start(sx, 184, CrossX, CrossY);
|
missile_start(sx, 184, cx, cy);
|
||||||
|
|
||||||
// Reset request
|
// Reset request
|
||||||
CrossP = false;
|
CrossP = false;
|
||||||
|
|
|
@ -48,7 +48,7 @@ struct Point
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Point tcorners[8], pcorners[8];
|
__striped Point tcorners[8], pcorners[8];
|
||||||
|
|
||||||
void drawCube(void)
|
void drawCube(void)
|
||||||
{
|
{
|
||||||
|
@ -77,6 +77,45 @@ void hideCube(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void xorCube(void)
|
||||||
|
{
|
||||||
|
for(char i=0; i<8; i++)
|
||||||
|
{
|
||||||
|
if (!(i & 1))
|
||||||
|
bm_line(&Screen, &cr, tcorners[i].x, tcorners[i].y, tcorners[i | 1].x, tcorners[i | 1].y, 0xff, LINOP_XOR);
|
||||||
|
if (!(i & 2))
|
||||||
|
bm_line(&Screen, &cr, tcorners[i].x, tcorners[i].y, tcorners[i | 2].x, tcorners[i | 2].y, 0xff, LINOP_XOR);
|
||||||
|
if (!(i & 4))
|
||||||
|
bm_line(&Screen, &cr, tcorners[i].x, tcorners[i].y, tcorners[i | 4].x, tcorners[i | 4].y, 0xff, LINOP_XOR);
|
||||||
|
pcorners[i] = tcorners[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void xor2Cube(void)
|
||||||
|
{
|
||||||
|
for(char i=0; i<8; i++)
|
||||||
|
{
|
||||||
|
if (!(i & 1))
|
||||||
|
{
|
||||||
|
bm_line(&Screen, &cr, pcorners[i].x, pcorners[i].y, pcorners[i | 1].x, pcorners[i | 1].y, 0xff, LINOP_XOR);
|
||||||
|
bm_line(&Screen, &cr, tcorners[i].x, tcorners[i].y, tcorners[i | 1].x, tcorners[i | 1].y, 0xff, LINOP_XOR);
|
||||||
|
}
|
||||||
|
if (!(i & 2))
|
||||||
|
{
|
||||||
|
bm_line(&Screen, &cr, pcorners[i].x, pcorners[i].y, pcorners[i | 2].x, pcorners[i | 2].y, 0xff, LINOP_XOR);
|
||||||
|
bm_line(&Screen, &cr, tcorners[i].x, tcorners[i].y, tcorners[i | 2].x, tcorners[i | 2].y, 0xff, LINOP_XOR);
|
||||||
|
}
|
||||||
|
if (!(i & 4))
|
||||||
|
{
|
||||||
|
bm_line(&Screen, &cr, pcorners[i].x, pcorners[i].y, pcorners[i | 4].x, pcorners[i | 4].y, 0xff, LINOP_XOR);
|
||||||
|
bm_line(&Screen, &cr, tcorners[i].x, tcorners[i].y, tcorners[i | 4].x, tcorners[i | 4].y, 0xff, LINOP_XOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(char i=0; i<8; i++)
|
||||||
|
pcorners[i] = tcorners[i];
|
||||||
|
}
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
|
|
||||||
F12Vector3 corners[8];
|
F12Vector3 corners[8];
|
||||||
|
@ -112,8 +151,15 @@ int main(void)
|
||||||
tcorners[i].y = lmuldiv16s(vd.v[1], 140, vd.v[2] + 4 * FIX12_ONE) + 100;
|
tcorners[i].y = lmuldiv16s(vd.v[1], 140, vd.v[2] + 4 * FIX12_ONE) + 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
if (k)
|
||||||
|
xor2Cube();
|
||||||
|
else
|
||||||
|
xorCube();
|
||||||
|
#else
|
||||||
hideCube();
|
hideCube();
|
||||||
drawCube();
|
drawCube();
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ __interrupt void doscroll(void)
|
||||||
vic.color_border++;
|
vic.color_border++;
|
||||||
|
|
||||||
// Update raster IRQ for scroll line with new horizontal scroll offset
|
// Update raster IRQ for scroll line with new horizontal scroll offset
|
||||||
rirq_data(&scroll, 0, 7 - (x & 7));
|
rirq_data(&scroll, 1, 7 - (x & 7));
|
||||||
// Copy scrolled version of text when switching over char border
|
// Copy scrolled version of text when switching over char border
|
||||||
if ((x & 7) == 0)
|
if ((x & 7) == 0)
|
||||||
memcpy((char *)0x0400 + 40 * 24, Text + ((x >> 3) & 255), 40);
|
memcpy((char *)0x0400 + 40 * 24, Text + ((x >> 3) & 255), 40);
|
||||||
|
@ -37,11 +37,13 @@ int main(void)
|
||||||
rirq_init(true);
|
rirq_init(true);
|
||||||
|
|
||||||
// Build switch to scroll line IRQ
|
// Build switch to scroll line IRQ
|
||||||
rirq_build(&scroll, 1);
|
rirq_build(&scroll, 2);
|
||||||
|
// Delay for one line to get to right border
|
||||||
|
rirq_delay(&scroll, 11);
|
||||||
// Change control register two with this IRQ
|
// Change control register two with this IRQ
|
||||||
rirq_write(&scroll, 0, &vic.ctrl2, 0);
|
rirq_write(&scroll, 1, &vic.ctrl2, 0);
|
||||||
// Put it onto the scroll line
|
// Put it onto the scroll line
|
||||||
rirq_set(0, 50 + 24 * 8, &scroll);
|
rirq_set(0, 49 + 24 * 8, &scroll);
|
||||||
|
|
||||||
// Build the switch to normal IRQ
|
// Build the switch to normal IRQ
|
||||||
rirq_build(&restore, 2);
|
rirq_build(&restore, 2);
|
||||||
|
|
|
@ -20,11 +20,13 @@ int main(void)
|
||||||
rirq_init(true);
|
rirq_init(true);
|
||||||
|
|
||||||
// Build switch to scroll line IRQ
|
// Build switch to scroll line IRQ
|
||||||
rirq_build(&scroll, 1);
|
rirq_build(&scroll, 2);
|
||||||
|
// Delay for one line to get to right border
|
||||||
|
rirq_delay(&scroll, 11);
|
||||||
// Change control register two with this IRQ
|
// Change control register two with this IRQ
|
||||||
rirq_write(&scroll, 0, &vic.ctrl2, 0);
|
rirq_write(&scroll, 1, &vic.ctrl2, 0);
|
||||||
// Put it onto the scroll line
|
// Put it onto the scroll line
|
||||||
rirq_set(0, 50 + 24 * 8, &scroll);
|
rirq_set(0, 49 + 24 * 8, &scroll);
|
||||||
|
|
||||||
// Build the switch to normal IRQ
|
// Build the switch to normal IRQ
|
||||||
rirq_build(&bottom, 1);
|
rirq_build(&bottom, 1);
|
||||||
|
@ -46,7 +48,7 @@ int main(void)
|
||||||
// wait for raster reaching bottom of screen
|
// wait for raster reaching bottom of screen
|
||||||
rirq_wait();
|
rirq_wait();
|
||||||
// Update raster IRQ for scroll line with new horizontal scroll offset
|
// Update raster IRQ for scroll line with new horizontal scroll offset
|
||||||
rirq_data(&scroll, 0, 7 - (x & 7));
|
rirq_data(&scroll, 1, 7 - (x & 7));
|
||||||
// Copy scrolled version of text when switching over char border
|
// Copy scrolled version of text when switching over char border
|
||||||
if ((x & 7) == 0)
|
if ((x & 7) == 0)
|
||||||
memcpy((char *)0x0400 + 40 * 24, Text + ((x >> 3) & 255), 40);
|
memcpy((char *)0x0400 + 40 * 24, Text + ((x >> 3) & 255), 40);
|
||||||
|
|
|
@ -27,7 +27,7 @@ ScreenRow * const color = (ScreenRow *)0xd800;
|
||||||
// Move the screen one character to the left
|
// Move the screen one character to the left
|
||||||
void scrollLeft(void)
|
void scrollLeft(void)
|
||||||
{
|
{
|
||||||
// Loop horizontaly
|
// Loop horizontally
|
||||||
for(char x=0; x<39; x++)
|
for(char x=0; x<39; x++)
|
||||||
{
|
{
|
||||||
// Unroll vertical loop 16 times
|
// Unroll vertical loop 16 times
|
||||||
|
|
|
@ -64,6 +64,7 @@ const char * scrolltext[] = {
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
|
""
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -198,7 +199,7 @@ int main(void)
|
||||||
// Update interrupt position
|
// Update interrupt position
|
||||||
for(char i=0; i<5; i++)
|
for(char i=0; i<5; i++)
|
||||||
{
|
{
|
||||||
int ty = 48 * i + 46 + oy;
|
int ty = 48 * i + 45 + oy;
|
||||||
|
|
||||||
// No interrupts below screen bottom
|
// No interrupts below screen bottom
|
||||||
if (ty < 250)
|
if (ty < 250)
|
||||||
|
@ -246,7 +247,7 @@ int main(void)
|
||||||
case 42:
|
case 42:
|
||||||
readline(line, lpos);
|
readline(line, lpos);
|
||||||
lpos++;
|
lpos++;
|
||||||
if (lpos == 28)
|
if (lpos == 27)
|
||||||
lpos = 0;
|
lpos = 0;
|
||||||
break;
|
break;
|
||||||
case 45:
|
case 45:
|
||||||
|
|
Loading…
Reference in New Issue