mirror of
https://github.com/ksherlock/x65.git
synced 2024-06-01 12:41:28 +00:00
Compare commits
159 Commits
931eeac653
...
9e542033b8
Author | SHA1 | Date | |
---|---|---|---|
|
9e542033b8 | ||
|
842b68b342 | ||
|
c4dff1c872 | ||
|
d4345a2352 | ||
|
3edff374c9 | ||
|
73eaa45daa | ||
|
101e6ed3de | ||
|
5339e5c789 | ||
|
4a88deb989 | ||
|
74d517e9d3 | ||
|
1928206659 | ||
|
bed84e27cf | ||
|
dc53ab5174 | ||
|
3596224b3c | ||
|
e0d3f3c9cd | ||
|
2bbe8aab66 | ||
|
88fc0cbb60 | ||
|
efb99fe9ab | ||
|
779c7af7ed | ||
|
063459efbf | ||
|
f67a920a06 | ||
|
b75a8325ee | ||
|
7df69d5e36 | ||
|
56fb34c64b | ||
|
c1fa69d90f | ||
|
5c98f7c7e8 | ||
|
060be58f41 | ||
|
1d70c9b963 | ||
|
f3b33acf88 | ||
|
98ceceb315 | ||
|
3a33dc7056 | ||
|
87d88265b0 | ||
|
8e95b7ffb9 | ||
|
2a2529f237 | ||
|
45b998fa2b | ||
|
bf6c7b0df9 | ||
|
af8c7ae42d | ||
|
34b3c1edb9 | ||
|
fe924aab14 | ||
|
4a81aafdc7 | ||
|
295129cd6c | ||
|
da6ed1159d | ||
|
06aae43fdd | ||
|
a2d9c5330d | ||
|
c2492ab348 | ||
|
1f6956c1ec | ||
|
45f5d05f54 | ||
|
56b253880e | ||
|
e6a63010f2 | ||
|
b8ef00f811 | ||
|
1f61d948fb | ||
|
17a99e46e7 | ||
|
fd1bc0ba76 | ||
|
b699c1b6f4 | ||
|
c1de91e3f1 | ||
|
53f69edc5a | ||
|
d80f5473a2 | ||
|
6af905353c | ||
|
dda49fda57 | ||
|
846bd5cd63 | ||
|
09796bc6e7 | ||
|
b45da90bce | ||
|
33e7f72d0b | ||
|
5cec8f8309 | ||
|
e3fa7b0c83 | ||
|
b469ceef8c | ||
|
eb3df4de88 | ||
|
4b7e679b20 | ||
|
a535295929 | ||
|
758b4349eb | ||
|
600567a42e | ||
|
385155d5eb | ||
|
b3d9b40563 | ||
|
12e158d637 | ||
|
a3f8a7cf44 | ||
|
66bdac5079 | ||
|
6e4be1504d | ||
|
963d1925cc | ||
|
c234531d69 | ||
|
019e8d7ae9 | ||
|
2243803116 | ||
|
d5080e925d | ||
|
7521d31514 | ||
|
33b229d00a | ||
|
6e8a41acc1 | ||
|
de0bc5120f | ||
|
482470b410 | ||
|
23aedcf686 | ||
|
da015f3e1c | ||
|
4670be0ce1 | ||
|
efacecf701 | ||
|
4c3c1654fb | ||
|
cfb2d1a8d8 | ||
|
ab2015fc3d | ||
|
eae936dd6a | ||
|
4285a14801 | ||
|
b16edcd592 | ||
|
05b7e253c3 | ||
|
efc63864ee | ||
|
2698f08ab9 | ||
|
9c7f413dac | ||
|
49ca89f875 | ||
|
479300eec7 | ||
|
effd8205db | ||
|
adcefe4bff | ||
|
e37bf5ae11 | ||
|
576ec5497d | ||
|
baebdbe096 | ||
|
fe049342bd | ||
|
8f4a00e3ce | ||
|
c226b00dad | ||
|
b4407f7cb5 | ||
|
a0b73db5c8 | ||
|
03f5e5cbfe | ||
|
e452d3ab7e | ||
|
9752c1d8a1 | ||
|
73d67d0657 | ||
|
0fcdc9ca47 | ||
|
d1c9f3aab5 | ||
|
07b1a52bb4 | ||
|
4f6db98637 | ||
|
d9d386a260 | ||
|
273bdcc92d | ||
|
ee53c41776 | ||
|
341cc8f2ad | ||
|
462eaeccf6 | ||
|
0605a1d6d2 | ||
|
7d59943d35 | ||
|
60780a514a | ||
|
5b9e5f6d46 | ||
|
1f50f07c24 | ||
|
e3241c66aa | ||
|
794171d48b | ||
|
7833ddc188 | ||
|
c4921552ba | ||
|
b8362cbb0b | ||
|
ec01fcc6e1 | ||
|
5dbe08b1b3 | ||
|
3b2b0f7778 | ||
|
0f740c25bd | ||
|
c96399d896 | ||
|
214c32931a | ||
|
798b657c70 | ||
|
a674f7f165 | ||
|
0e64a58375 | ||
|
acf26cf7d7 | ||
|
9cdfeeb0ca | ||
|
6cbf7f8754 | ||
|
260f48e126 | ||
|
72b81efc87 | ||
|
2919e0556c | ||
|
6adcdc92b6 | ||
|
65f19b4a47 | ||
|
bdc013350c | ||
|
f6531d3bbc | ||
|
482640fb1e | ||
|
9f8ad61fe2 | ||
|
5459c6c0e0 | ||
|
05bdc73b86 |
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
|||
./x65.exe
|
||||
*.suo
|
||||
*.ipch
|
||||
*.aps
|
||||
|
@ -18,4 +19,5 @@
|
|||
*.obj.enc
|
||||
*.user
|
||||
*.db*
|
||||
*.recipe
|
||||
test/results/*
|
|
@ -62,8 +62,7 @@ x65.cpp requires struse.h which is a single file text parsing library that can b
|
|||
|
||||
### Download Binaries
|
||||
|
||||
* [Windows x64 binaries](../..//raw/master/bin/x65_x64.zip)
|
||||
* [Windows x86 binaries](../..//raw/master/bin/x65_win32.zip)
|
||||
Please note that releases have moved the Github [releases](https://github.com/Sakrac/x65/releases)
|
||||
|
||||
### x65
|
||||
|
||||
|
@ -102,6 +101,7 @@ Primarily tested with personal archive of sources written for Kick assmebler, DA
|
|||
* irp (indefinite repeat)
|
||||
|
||||
**FIXED**
|
||||
* Source Debug output file including linkable object files, C64Debugger format
|
||||
* Adding MERGE directive, Label Pools rewrite, TEXT data can be indexed from a string symbol
|
||||
* Label Pools were destroyed after each scope so they did not work in include files which defeated their purpose. Label pools are now persistent through scopes.
|
||||
* Labels reserved from label pools now distinguish between global and local. Use [.!@$] as a prefix to reserve a local label from a label pool (previously always local)
|
||||
|
|
Binary file not shown.
BIN
bin/x65_x64.zip
BIN
bin/x65_x64.zip
Binary file not shown.
0
obj/x64Releasex65/x65.vcxproj.FileListAbsolute.txt
Normal file
0
obj/x64Releasex65/x65.vcxproj.FileListAbsolute.txt
Normal file
|
@ -23,32 +23,32 @@
|
|||
<ProjectGuid>{57EFF4A4-7BF2-43F0-AD62-A79092DA67D1}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>dump_x65</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -23,32 +23,32 @@
|
|||
<ProjectGuid>{2823019A-A423-4A40-BB9C-5CE242019BD0}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>x65</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
</PropertyGroup>
|
||||
|
|
21
struse.h
21
struse.h
|
@ -590,6 +590,7 @@ public:
|
|||
strref split_token_trim(char c);
|
||||
strref split_token_any_trim(const strref chars);
|
||||
strref split_token_track_parens(char c);
|
||||
strref split_token_track_parens_quote(char c);
|
||||
strref split_token_trim_track_parens(char c);
|
||||
strref split_range(const strref range, strl_t pos=0);
|
||||
strref split_range_trim(const strref range, strl_t pos=0);
|
||||
|
@ -770,7 +771,7 @@ public:
|
|||
int find_after_last(char a, char b) const { return get_strref().find_after_last(a, b); }
|
||||
int find_after_last(char a1, char a2, char b) const { return get_strref().find_after_last(a1, a2, b); }
|
||||
int find(const strref str) const { return get_strref().find(str); }
|
||||
int find(const strref str, strl_t pos) const { get_strref().find(str, pos); }
|
||||
int find(const strref str, strl_t pos) const { return get_strref().find(str, pos); }
|
||||
int find(const char *str, strl_t pos = 0) const { return get_strref().find(str, pos); }
|
||||
int find_case(const strref str) const { return get_strref().find_case(str); }
|
||||
int find_case(const char *str) const { return get_strref().find_case(str); }
|
||||
|
@ -4162,6 +4163,24 @@ strref strref::split_token_track_parens(char c)
|
|||
return r;
|
||||
}
|
||||
|
||||
strref strref::split_token_track_parens_quote(char c)
|
||||
{
|
||||
if (length>=2 && string[0] == '"') {
|
||||
strl_t o = 1;
|
||||
while (o < length && string[o] != '"') { ++o; }
|
||||
if (o < length) {
|
||||
strref r = strref(string, o + 1);
|
||||
*this += o + 1;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
int t = find_skip_parens(c);
|
||||
if (t < 0) t = (int)length;
|
||||
strref r = strref(string, strl_t(t));
|
||||
*this += t + 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
strref strref::split_token_any( const strref chars )
|
||||
{
|
||||
strref r; int t = find_any_char_of( chars );
|
||||
|
|
8
test/merlin_data.s
Normal file
8
test/merlin_data.s
Normal file
|
@ -0,0 +1,8 @@
|
|||
; merlin_data.s
|
||||
db $12,$34,$56,$78
|
||||
ddb $1234,$5678 ; double byte - big endian format.
|
||||
dw $1234
|
||||
da $1234
|
||||
adr $123456
|
||||
adrl $12345678
|
||||
|
500
x65.cpp
500
x65.cpp
|
@ -41,8 +41,13 @@
|
|||
#include <inttypes.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#define _strdup strdup
|
||||
#endif
|
||||
|
||||
// Command line arguments
|
||||
static const strref cmdarg_listing("lst"); // -lst / -lst=(file.lst) : generate disassembly text from result(file or stdout)
|
||||
static const strref cmdarg_srcdebug("srcdbg"); // -srcdbg : generate debug, -srcdbg=(file) : save debug file
|
||||
static const strref cmdarg_tass_listing("tsl"); // -tsl=(file) : generate listing file in TASS style
|
||||
static const strref cmdarg_tass_labels("tl"); // -tl=(file) : generate labels in TASS style
|
||||
static const strref cmdarg_allinstr("opcodes"); // -opcodes / -opcodes=(file.s) : dump all available opcodes(file or stdout)
|
||||
|
@ -322,6 +327,7 @@ enum AssemblerDirective {
|
|||
AD_ENT, // ENT: MERLIN extern this address label
|
||||
AD_EXT, // EXT: MERLIN reference this address label from a different file
|
||||
AD_CYC, // CYC: MERLIN start / stop cycle timer
|
||||
AD_DBL_BYTES, // DDB: MERLIN Store 2 bytes, big endian format.
|
||||
AD_ERROR,
|
||||
};
|
||||
|
||||
|
@ -473,7 +479,7 @@ enum AddrMode {
|
|||
|
||||
// 6502 illegal modes
|
||||
AMM_SLO = AMM_ZP | AMM_ZP_X | AMM_ABS | AMM_ABS_Y | AMM_ABS_X | AMM_ZP_REL_X | AMM_ZP_Y_REL,
|
||||
AMM_SAX = AMM_FLIPXY | AMM_ZP | AMM_ZP_X | AMM_ZP_REL_X | AMM_ABS,
|
||||
AMM_AXS = AMM_FLIPXY | AMM_ZP | AMM_ZP_X | AMM_ZP_REL_X | AMM_ABS,
|
||||
AMM_LAX = AMM_FLIPXY | AMM_ZP | AMM_ZP_X | AMM_ZP_REL_X | AMM_ABS | AMM_ABS_X | AMM_ZP_Y_REL,
|
||||
AMM_AHX = AMM_FLIPXY | AMM_ZP_REL_X | AMM_ABS_X,
|
||||
AMM_SHY = AMM_ABS_X,
|
||||
|
@ -582,7 +588,7 @@ struct mnem opcodes_6502[] = {
|
|||
{ "rla", AMM_SLO, { 0x23, 0x27, 0x00, 0x2f, 0x33, 0x37, 0x3b, 0x3f, 0x00, 0x00, 0x00 } },
|
||||
{ "sre", AMM_SLO, { 0x43, 0x47, 0x00, 0x4f, 0x53, 0x57, 0x5b, 0x5f, 0x00, 0x00, 0x00 } },
|
||||
{ "rra", AMM_SLO, { 0x63, 0x67, 0x00, 0x6f, 0x73, 0x77, 0x7b, 0x7f, 0x00, 0x00, 0x00 } },
|
||||
{ "sax", AMM_SAX, { 0x83, 0x87, 0x00, 0x8f, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ "sax", AMM_IMM, { 0x00, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ "lax", AMM_LAX, { 0xa3, 0xa7, 0x00, 0xaf, 0xb3, 0xb7, 0x00, 0xbf, 0x00, 0x00, 0x00 } },
|
||||
{ "dcp", AMM_SLO, { 0xc3, 0xc7, 0x00, 0xcf, 0xd3, 0xd7, 0xdb, 0xdf, 0x00, 0x00, 0x00 } },
|
||||
{ "isc", AMM_SLO, { 0xe3, 0xe7, 0x00, 0xef, 0xf3, 0xf7, 0xfb, 0xff, 0x00, 0x00, 0x00 } },
|
||||
|
@ -592,7 +598,7 @@ struct mnem opcodes_6502[] = {
|
|||
{ "arr", AMM_IMM, { 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ "xaa", AMM_IMM, { 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{"lax2", AMM_IMM, { 0x00, 0x00, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ "axs", AMM_IMM, { 0x00, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ "axs", AMM_AXS, { 0x83, 0x87, 0x00, 0x8f, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ "sbi", AMM_IMM, { 0x00, 0x00, 0xeb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ "ahx", AMM_AHX, { 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00 } },
|
||||
{ "shy", AMM_SHY, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00 } },
|
||||
|
@ -608,14 +614,23 @@ const char* aliases_6502[] = {
|
|||
};
|
||||
|
||||
uint8_t timing_6502[] = {
|
||||
0x0e, 0x0c, 0xff, 0xff, 0xff, 0x06, 0x0a, 0xff, 0x06, 0x04, 0x04, 0xff, 0xff, 0x08, 0x0c, 0xff, 0x05, 0x0b, 0xff, 0xff, 0xff, 0x08, 0x0c, 0xff, 0x04, 0x09, 0xff, 0xff, 0xff, 0x09, 0x0e, 0xff,
|
||||
0x0c, 0x0c, 0xff, 0xff, 0x06, 0x06, 0x0a, 0xff, 0x08, 0x04, 0x04, 0xff, 0x08, 0x08, 0x0c, 0xff, 0x05, 0x0b, 0xff, 0xff, 0xff, 0x08, 0x0c, 0xff, 0x04, 0x09, 0xff, 0xff, 0xff, 0x09, 0x0e, 0xff,
|
||||
0x0c, 0x0c, 0xff, 0xff, 0xff, 0x06, 0x0a, 0xff, 0x06, 0x04, 0x04, 0xff, 0x06, 0x08, 0x0c, 0xff, 0x05, 0x0b, 0xff, 0xff, 0xff, 0x08, 0x0c, 0xff, 0x04, 0x09, 0xff, 0xff, 0xff, 0x09, 0x0e, 0xff,
|
||||
0x0c, 0x0c, 0xff, 0xff, 0xff, 0x06, 0x0a, 0xff, 0x08, 0x04, 0x04, 0xff, 0x0a, 0x08, 0x0c, 0xff, 0x05, 0x0b, 0xff, 0xff, 0xff, 0x08, 0x0c, 0xff, 0x04, 0x09, 0xff, 0xff, 0xff, 0x09, 0x0e, 0xff,
|
||||
0xff, 0x0c, 0xff, 0xff, 0x06, 0x06, 0x06, 0xff, 0x04, 0xff, 0x04, 0xff, 0x08, 0x08, 0x08, 0xff, 0x05, 0x0c, 0xff, 0xff, 0x08, 0x08, 0x08, 0xff, 0x04, 0x0a, 0x04, 0xff, 0xff, 0x0a, 0xff, 0xff,
|
||||
0x04, 0x0c, 0x04, 0xff, 0x06, 0x06, 0x06, 0xff, 0x04, 0x04, 0x04, 0xff, 0x08, 0x08, 0x08, 0xff, 0x05, 0x0b, 0xff, 0xff, 0x08, 0x08, 0x08, 0xff, 0x04, 0x09, 0x04, 0xff, 0x09, 0x09, 0x09, 0xff,
|
||||
0x04, 0x0c, 0xff, 0xff, 0x06, 0x06, 0x0a, 0xff, 0x04, 0x04, 0x04, 0xff, 0x08, 0x08, 0x0c, 0xff, 0x05, 0x0b, 0xff, 0xff, 0xff, 0x08, 0x0c, 0xff, 0x04, 0x09, 0xff, 0xff, 0xff, 0x09, 0x0e, 0xff,
|
||||
0x04, 0x0c, 0xff, 0xff, 0x06, 0x06, 0x0a, 0xff, 0x04, 0x04, 0x04, 0xff, 0x08, 0x08, 0x0c, 0xff, 0x05, 0x0b, 0xff, 0xff, 0xff, 0x08, 0x0c, 0xff, 0x04, 0x09, 0xff, 0xff, 0xff, 0x09, 0x0e, 0xff
|
||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
0x0e, 0x0c, 0xff, 0x0f, 0xff, 0x06, 0x0a, 0x0a, 0x06, 0x04, 0x04, 0x04, 0x04, 0x08, 0x0c, 0x0c, // 0
|
||||
0x05, 0x0b, 0xff, 0x0f, 0xff, 0x08, 0x0c, 0x0c, 0x04, 0x09, 0x02, 0x0e, 0x04, 0x09, 0x0e, 0x0f, // 1
|
||||
0x0c, 0x0c, 0xff, 0x0f, 0x06, 0x06, 0x0a, 0x0a, 0x08, 0x04, 0x04, 0x04, 0x08, 0x08, 0x0c, 0x0c, // 2
|
||||
0x05, 0x0b, 0xff, 0x0f, 0xff, 0x08, 0x0c, 0x0c, 0x04, 0x09, 0x02, 0x0e, 0x04, 0x09, 0x0e, 0x0f, // 3
|
||||
0x0c, 0x0c, 0xff, 0x0f, 0xff, 0x06, 0x0a, 0x0a, 0x06, 0x04, 0x04, 0x04, 0x06, 0x08, 0x0c, 0x0c, // 4
|
||||
0x05, 0x0b, 0xff, 0x0f, 0xff, 0x08, 0x0c, 0x0c, 0x04, 0x09, 0x02, 0xff, 0x04, 0x09, 0x0e, 0x0f, // 5
|
||||
0x0c, 0x0c, 0xff, 0x0f, 0xff, 0x06, 0x0a, 0x0a, 0x08, 0x04, 0x04, 0x04, 0x0a, 0x08, 0x0c, 0x0c, // 6
|
||||
0x05, 0x0b, 0xff, 0x0f, 0xff, 0x08, 0x0c, 0x0c, 0x04, 0x09, 0x02, 0x0e, 0x04, 0x09, 0x0e, 0x0f, // 7
|
||||
0xff, 0x0c, 0xff, 0x0c, 0x06, 0x06, 0x06, 0x06, 0x04, 0xff, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, // 8
|
||||
0x05, 0x0c, 0xff, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x04, 0x0a, 0x04, 0x0a, 0x05, 0x0a, 0x05, 0x0a, // 9
|
||||
0x04, 0x0c, 0x04, 0x0c, 0x06, 0x06, 0x06, 0x06, 0x04, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, // A
|
||||
0x05, 0x0b, 0xff, 0x0a, 0x08, 0x08, 0x08, 0x08, 0x04, 0x09, 0x04, 0x09, 0x09, 0x09, 0x09, 0x0a, // B
|
||||
0x04, 0x0c, 0xff, 0x0f, 0x06, 0x06, 0x0a, 0x0a, 0x04, 0x04, 0x04, 0x04, 0x08, 0x08, 0x0c, 0x0c, // C
|
||||
0x05, 0x0b, 0xff, 0x0f, 0xff, 0x08, 0x0c, 0x0c, 0x04, 0x09, 0x02, 0x0e, 0x04, 0x09, 0x0e, 0x0e, // D
|
||||
0x04, 0x0c, 0xff, 0xff, 0x06, 0x06, 0x0a, 0x0a, 0x04, 0x04, 0x04, 0x04, 0x08, 0x08, 0x0c, 0x0c, // E
|
||||
0x05, 0x0b, 0xff, 0xff, 0xff, 0x08, 0x0c, 0x0c, 0x04, 0x09, 0x02, 0x0e, 0x04, 0x09, 0x0e, 0x0e // F
|
||||
};
|
||||
|
||||
static const int num_opcodes_6502 = sizeof(opcodes_6502) / sizeof(opcodes_6502[0]);
|
||||
|
@ -1057,7 +1072,7 @@ DirectiveName aDirectiveNamesMerlin[] {
|
|||
{ "DW", AD_WORDS }, // MERLIN
|
||||
{ "ASC", AD_TEXT }, // MERLIN
|
||||
{ "PUT", AD_INCLUDE }, // MERLIN
|
||||
{ "DDB", AD_WORDS }, // MERLIN
|
||||
{ "DDB", AD_DBL_BYTES }, // MERLIN
|
||||
{ "DB", AD_BYTES }, // MERLIN
|
||||
{ "DFB", AD_BYTES }, // MERLIN
|
||||
{ "HEX", AD_HEX }, // MERLIN
|
||||
|
@ -1128,6 +1143,13 @@ uint32_t FindLabelIndex(uint32_t hash, uint32_t *table, uint32_t count)
|
|||
return count;
|
||||
}
|
||||
|
||||
char* StringCopy(strref str)
|
||||
{
|
||||
char* buf = (char*)calloc(1, (size_t)str.get_len() + 1);
|
||||
if (buf && str.get_len()) { memcpy(buf, str.get(), str.get_len()); }
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
|
@ -1216,7 +1238,7 @@ template< class KeyType, class ValueType, class CountType = size_t > struct Hash
|
|||
KeyType* keys;
|
||||
ValueType* values;
|
||||
|
||||
static CountType HashFunction(KeyType v) { return CountType(((v + (v >> 27) + (v << 29)) + 14695981039346656037) * 1099511628211); }
|
||||
static CountType HashFunction(KeyType v) { return CountType(((v + (v >> 27) + (v << 29)) + 14695981039346656037UL) * 1099511628211UL); }
|
||||
static CountType HashIndex(KeyType hash, CountType tableSize) { return hash & (tableSize - 1); }
|
||||
static CountType GetNextIndex(KeyType hash, CountType tableSize) { return (hash + 1) & (tableSize - 1); }
|
||||
static CountType KeyToIndex(KeyType key, CountType tableSize) { return HashIndex(HashFunction(key), tableSize); }
|
||||
|
@ -1406,6 +1428,7 @@ struct ListLine {
|
|||
};
|
||||
strref source_name; // source file index name
|
||||
strref code; // line of code this represents
|
||||
int column; // column of line
|
||||
int address; // start address of this line
|
||||
int size; // number of bytes generated for this line
|
||||
int line_offs; // offset into code
|
||||
|
@ -1422,10 +1445,17 @@ typedef std::vector<struct ListLine> Listing;
|
|||
struct SourceDebugEntry {
|
||||
int source_file_index; // index into Assembler::source_file vector
|
||||
int address; // local address in section
|
||||
int size;
|
||||
int source_file_offset; // can be converted into line/column while linking
|
||||
int size:24;
|
||||
int type : 8;
|
||||
};
|
||||
typedef std::vector<struct SLDEntry> SourceDebug;
|
||||
enum class SourceDebugType {
|
||||
Code,
|
||||
Label,
|
||||
Breakpoint
|
||||
};
|
||||
|
||||
typedef std::vector<struct SourceDebugEntry> SourceDebug;
|
||||
|
||||
|
||||
enum SectionType : int8_t { // enum order indicates fixed address linking priority
|
||||
|
@ -1507,6 +1537,8 @@ typedef struct Section {
|
|||
pRelocs = nullptr;
|
||||
if (pListing) delete pListing;
|
||||
pListing = nullptr;
|
||||
if (pSrcDbg) delete pSrcDbg;
|
||||
pSrcDbg = nullptr;
|
||||
}
|
||||
|
||||
void Cleanup() { if (output) free(output); reset(); }
|
||||
|
@ -1530,11 +1562,11 @@ typedef struct Section {
|
|||
void AddReloc(int base, int offset, int section, int8_t bytes, int8_t shift);
|
||||
|
||||
Section() : pRelocs(nullptr), pListing(nullptr) { reset(); }
|
||||
Section(strref _name, int _address) : pRelocs(nullptr), pListing(nullptr) {
|
||||
Section(strref _name, int _address) : pRelocs(nullptr), pListing(nullptr), pSrcDbg(nullptr) {
|
||||
reset(); name = _name; start_address = load_address = address = _address;
|
||||
address_assigned = true;
|
||||
}
|
||||
Section(strref _name) : pRelocs(nullptr), pListing(nullptr) {
|
||||
Section(strref _name) : pRelocs(nullptr), pListing(nullptr), pSrcDbg(nullptr) {
|
||||
reset(); name = _name;
|
||||
start_address = load_address = address = 0; address_assigned = false;
|
||||
}
|
||||
|
@ -1559,6 +1591,7 @@ struct MapSymbol {
|
|||
strref name; // string name
|
||||
int value;
|
||||
int16_t section;
|
||||
int16_t orig_section;
|
||||
bool local; // local variables
|
||||
};
|
||||
typedef std::vector<struct MapSymbol> MapSymbolArray;
|
||||
|
@ -1570,6 +1603,7 @@ public:
|
|||
strref pool_name; // name of the pool that this label is related to
|
||||
int value;
|
||||
int section; // rel section address labels belong to a section, -1 if fixed address or assigned
|
||||
int orig_section; // original section where the label was defined
|
||||
int mapIndex; // index into map symbols in case of late resolve
|
||||
bool evaluated; // a value may not yet be evaluated
|
||||
bool pc_relative; // this is an inline label describing a point in the code
|
||||
|
@ -1591,6 +1625,7 @@ typedef struct sLateEval {
|
|||
LET_BRANCH, // calculate a branch offset and store at this address
|
||||
LET_BRANCH_16, // calculate a branch offset of 16 bits and store at this address
|
||||
LET_BYTE, // calculate a byte and store at this address
|
||||
LET_DBL_BYTE, // calculate a 16-bit, big endian number.
|
||||
};
|
||||
int target; // offset into output buffer
|
||||
int address; // current pc
|
||||
|
@ -1812,6 +1847,7 @@ public:
|
|||
int8_t cycle_counter_level; // merlin toggles the cycle counter rather than hierarchically evals
|
||||
bool error_encountered; // if any error encountered, don't export binary
|
||||
bool list_assembly; // generate assembler listing
|
||||
bool src_debug; // generate source debug info
|
||||
bool end_macro_directive; // whether to use { } or macro / endmacro for macro scope
|
||||
bool import_means_xref;
|
||||
|
||||
|
@ -1828,6 +1864,9 @@ public:
|
|||
// Mimic TASS listing
|
||||
bool ListTassStyle( strref filename );
|
||||
|
||||
// Export C64Debugger dbg xml file
|
||||
bool SourceDebugExport(strref filename);
|
||||
|
||||
// Generate source for all valid instructions and addressing modes for current CPU
|
||||
bool AllOpcodes(strref filename);
|
||||
|
||||
|
@ -1920,6 +1959,9 @@ public:
|
|||
void MarkLabelLocal(strref label, bool scope_label = false);
|
||||
StatusCode FlushLocalLabels(int scope_exit = -1);
|
||||
|
||||
// Source debug
|
||||
void AddSrcDbg(int address, SourceDebugType type, const char* text);
|
||||
|
||||
// Label pools
|
||||
LabelPool* GetLabelPool(strref pool_name);
|
||||
StatusCode AddLabelPool(strref name, strref args);
|
||||
|
@ -1948,7 +1990,7 @@ public:
|
|||
StatusCode Directive_LNK(strref line);
|
||||
StatusCode Directive_XDEF(strref line);
|
||||
StatusCode Directive_XREF(strref label);
|
||||
StatusCode Directive_DC(strref line, int width, strref source_file);
|
||||
StatusCode Directive_DC(strref line, int width, strref source_file, bool little_endian = true);
|
||||
StatusCode Directive_DS(strref line);
|
||||
StatusCode Directive_ALIGN(strref line);
|
||||
StatusCode Directive_EVAL(strref line);
|
||||
|
@ -1994,7 +2036,7 @@ public:
|
|||
|
||||
// constructor
|
||||
Asm() : opcode_table(opcodes_6502), opcode_count(num_opcodes_6502), num_instructions(0),
|
||||
cpu(CPU_6502), list_cpu(CPU_6502) {
|
||||
cpu(CPU_6502), list_cpu(CPU_6502), lastEvalSection(-1) {
|
||||
Cleanup(); localLabels.reserve(256); loadedData.reserve(16); lateEval.reserve(64); }
|
||||
};
|
||||
|
||||
|
@ -2027,9 +2069,7 @@ void SymbolStackTable::PushSymbol(StringSymbol* string)
|
|||
ValueOrString val;
|
||||
val.string = nullptr;
|
||||
if (string->string_value) {
|
||||
val.string = (char*)malloc(string->string_value.get_len() + 1);
|
||||
memcpy(val.string, string->string_value.get(), string->string_value.get_len());
|
||||
val.string[string->string_value.get_len()] = 0;
|
||||
val.string = StringCopy(string->string_value.get_strref());
|
||||
}
|
||||
(*ppStack)->push_back(val);
|
||||
}
|
||||
|
@ -2136,8 +2176,12 @@ void Asm::Cleanup() {
|
|||
free(str.string_value.charstr());
|
||||
}
|
||||
strings.clear();
|
||||
for (std::vector<ExtLabels>::iterator exti = externals.begin(); exti !=externals.end(); ++exti)
|
||||
for (std::vector<ExtLabels>::iterator exti = externals.begin(); exti != externals.end(); ++exti) {
|
||||
exti->labels.clear();
|
||||
}
|
||||
for (std::vector<char*>::iterator src = source_files.begin(); src != source_files.end(); ++src) {
|
||||
free(*src);
|
||||
}
|
||||
externals.clear();
|
||||
// this section is relocatable but is assigned address $1000 if exporting without directives
|
||||
SetSection(strref("default,code"));
|
||||
|
@ -2152,6 +2196,7 @@ void Asm::Cleanup() {
|
|||
directive_scope_depth = 0;
|
||||
error_encountered = false;
|
||||
list_assembly = false;
|
||||
src_debug = false;
|
||||
end_macro_directive = false;
|
||||
import_means_xref = false;
|
||||
accumulator_16bit = false; // default 65816 8 bit immediate mode
|
||||
|
@ -2481,7 +2526,7 @@ uint8_t* Asm::BuildExport(strref append, int &file_size, int &addr) {
|
|||
(!i->include_from && allSections[first_link_section].include_from)))))
|
||||
first_link_section = SectionId(*i);
|
||||
has_relative_section = true;
|
||||
} else if (i->start_address >= 0x100 && ( i->size() > 0 || i->addr_size() > 0 ) ) {
|
||||
} else if (i->size() > 0 || i->addr_size() > 0) {
|
||||
has_fixed_section = true;
|
||||
bool inserted = false;
|
||||
for (std::vector<Section*>::iterator f = FixedExport.begin(); f != FixedExport.end(); ++f) {
|
||||
|
@ -2865,7 +2910,9 @@ StatusCode Asm::MergeSections(int section_id, int section_merge) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if(!s.IsRelativeSection()) { LinkLabelsToAddress(section_merge, -1, m.start_address); }
|
||||
if(!s.IsRelativeSection()) {
|
||||
LinkLabelsToAddress(section_merge, -1, s.start_address);
|
||||
}
|
||||
|
||||
// go through all labels referencing merging section
|
||||
for (uint32_t i = 0; i<labels.count(); i++) {
|
||||
|
@ -2914,6 +2961,20 @@ StatusCode Asm::MergeSections(int section_id, int section_merge) {
|
|||
delete m.pListing;
|
||||
m.pListing = nullptr;
|
||||
}
|
||||
// go through source debug
|
||||
if (m.pSrcDbg) {
|
||||
if (!s.pSrcDbg) { s.pSrcDbg = new SourceDebug; }
|
||||
if (s.pSrcDbg->capacity() < (m.pSrcDbg->size() + s.pSrcDbg->size())) {
|
||||
s.pSrcDbg->reserve((m.pSrcDbg->size() + s.pSrcDbg->size()));
|
||||
}
|
||||
for (SourceDebug::iterator i = m.pSrcDbg->begin(); i != m.pSrcDbg->end(); ++i) {
|
||||
SourceDebugEntry l = *i;
|
||||
l.address += addr_start;
|
||||
s.pSrcDbg->push_back(l);
|
||||
}
|
||||
delete m.pSrcDbg;
|
||||
m.pSrcDbg = nullptr;
|
||||
}
|
||||
m.type = ST_REMOVED;
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
@ -3067,6 +3128,16 @@ void Section::AddText(strref line, strref text_prefix) {
|
|||
if (CheckOutputCapacity((uint32_t)line.get_len()) == STATUS_OK) {
|
||||
if (!text_prefix || text_prefix.same_str("ascii")) {
|
||||
AddBin((const uint8_t*)line.get(), (int)line.get_len());
|
||||
} else if (text_prefix.same_str("c64screen")) {
|
||||
while (line) {
|
||||
char c = line.get_first(), o = c;
|
||||
if (c >= 'a' && c <= 'z') { o = c - 'a' + 1; }
|
||||
else if (c == '@') { o = 0; }
|
||||
else if (c == '[') { o = 27; }
|
||||
else if (c == ']') { o = 29; }
|
||||
AddByte(o >= 0x60 ? ' ' : o);
|
||||
++line;
|
||||
}
|
||||
} else if (text_prefix.same_str("petscii")) {
|
||||
while (line) {
|
||||
char c = line[0];
|
||||
|
@ -3350,8 +3421,8 @@ StatusCode Asm::BuildMacro(Macro &m, strref arg_list) {
|
|||
strref pchk = params;
|
||||
strref arg = arg_list;
|
||||
int dSize = 0;
|
||||
char token = arg_list.find(',')>=0 ? ',' : ' ';
|
||||
char token_macro = m.params_first_line && params.find(',') < 0 ? ' ' : ',';
|
||||
char token = ',';// arg_list.find(',') >= 0 ? ',' : ' ';
|
||||
char token_macro = ',';// m.params_first_line&& params.find(',') < 0 ? ' ' : ',';
|
||||
while (strref param = pchk.split_token_trim(token_macro)) {
|
||||
strref a = arg.split_token_trim(token);
|
||||
if (param.get_len() < a.get_len()) {
|
||||
|
@ -3365,7 +3436,7 @@ StatusCode Asm::BuildMacro(Macro &m, strref arg_list) {
|
|||
strovl macexp(buffer, mac_size);
|
||||
macexp.copy(macro_src);
|
||||
while (strref param = params.split_token_trim(token_macro)) {
|
||||
strref a = arg_list.split_token_trim(token);
|
||||
strref a = arg_list.split_token_track_parens_quote(token);
|
||||
macexp.replace_bookend(param, a, macro_arg_bookend);
|
||||
}
|
||||
PushContext(m.source_name, macexp.get_strref(), macexp.get_strref());
|
||||
|
@ -4257,6 +4328,23 @@ StatusCode Asm::CheckLateEval(strref added_label, int scope_end, bool print_miss
|
|||
allSections[sec].SetByte(trg, value);
|
||||
break;
|
||||
|
||||
case LateEval::LET_DBL_BYTE:
|
||||
if (ret==STATUS_RELATIVE_SECTION) {
|
||||
if (i->section<0) {
|
||||
resolved = false;
|
||||
} else {
|
||||
allSections[sec].AddReloc(lastEvalValue, trg, lastEvalSection, 1, lastEvalShift-8);
|
||||
allSections[sec].AddReloc(lastEvalValue, trg+1, lastEvalSection, 1, lastEvalShift);
|
||||
value = 0;
|
||||
}
|
||||
}
|
||||
if ((trg+1)>=allSections[sec].size()) {
|
||||
return ERROR_SECTION_TARGET_OFFSET_OUT_OF_RANGE;
|
||||
}
|
||||
allSections[sec].SetByte(trg, value>>8);
|
||||
allSections[sec].SetByte(trg+1, value);
|
||||
break;
|
||||
|
||||
case LateEval::LET_ABS_REF:
|
||||
if (ret==STATUS_RELATIVE_SECTION) {
|
||||
if (i->section<0) {
|
||||
|
@ -4327,6 +4415,7 @@ StatusCode Asm::CheckLateEval(strref added_label, int scope_end, bool print_miss
|
|||
label->value = value;
|
||||
label->evaluated = true;
|
||||
label->section = ret == STATUS_RELATIVE_SECTION ? i->section : -1;
|
||||
label->orig_section = i->section;
|
||||
if (num_new_labels<MAX_LABELS_EVAL_ALL) {
|
||||
new_labels[num_new_labels++] = label->label_name;
|
||||
}
|
||||
|
@ -4401,7 +4490,8 @@ void Asm::LabelAdded(Label *pLabel, bool local) {
|
|||
}
|
||||
MapSymbol sym;
|
||||
sym.name = pLabel->label_name;
|
||||
sym.section = (int16_t)(pLabel->section);
|
||||
sym.section = (int16_t)pLabel->section;
|
||||
sym.orig_section = (int16_t)pLabel->orig_section;
|
||||
sym.value = pLabel->value;
|
||||
sym.local = local;
|
||||
pLabel->mapIndex = pLabel->evaluated ? -1 : (int)map.size();
|
||||
|
@ -4574,6 +4664,7 @@ StatusCode Asm::AssignPoolLabel(LabelPool &pool, strref label) {
|
|||
pLabel->pool_name = pool.pool_name;
|
||||
pLabel->evaluated = true;
|
||||
pLabel->section = -1; // pool labels are section-less
|
||||
pLabel->orig_section = SectionId();
|
||||
pLabel->value = addr;
|
||||
pLabel->pc_relative = true;
|
||||
pLabel->constant = true;
|
||||
|
@ -4582,6 +4673,7 @@ StatusCode Asm::AssignPoolLabel(LabelPool &pool, strref label) {
|
|||
pLabel->referenced = false;
|
||||
bool local = false;
|
||||
|
||||
|
||||
if (label[ 0 ] == '.' || label[ 0 ] == '@' || label[ 0 ] == '!' || label[ 0 ] == ':' || label.get_last() == '$') {
|
||||
local = true;
|
||||
MarkLabelLocal( label, true );
|
||||
|
@ -4642,6 +4734,7 @@ StatusCode Asm::AssignLabel(strref label, strref expression, bool make_constant)
|
|||
pLabel->pool_name.clear();
|
||||
pLabel->evaluated = status==STATUS_OK || status == STATUS_RELATIVE_SECTION;
|
||||
pLabel->section = status == STATUS_RELATIVE_SECTION ? lastEvalSection : -1; // assigned labels are section-less
|
||||
pLabel->orig_section = lastEvalSection;
|
||||
pLabel->value = val;
|
||||
pLabel->mapIndex = -1;
|
||||
pLabel->pc_relative = false;
|
||||
|
@ -4676,12 +4769,15 @@ StatusCode Asm::AddressLabel(strref label)
|
|||
pLabel->label_name = label;
|
||||
pLabel->pool_name.clear();
|
||||
pLabel->section = CurrSection().IsRelativeSection() ? SectionId() : -1; // address labels are based on section
|
||||
pLabel->orig_section = SectionId();
|
||||
pLabel->value = CurrSection().GetPC();
|
||||
pLabel->evaluated = true;
|
||||
pLabel->pc_relative = true;
|
||||
pLabel->external = MatchXDEF(label);
|
||||
pLabel->reference = false;
|
||||
pLabel->constant = constLabel;
|
||||
// Label Source Debug Origin: AddSrcDbg((int)CurrSection().GetPC(), SourceDebugType::Label, label.get());
|
||||
|
||||
last_label = label;
|
||||
bool local = label[0]=='.' || label[0]=='@' || label[0]=='!' || label[0]==':' || label.get_last()=='$';
|
||||
if (directive_scope_depth > 0) { local = true; }
|
||||
|
@ -5388,7 +5484,7 @@ StatusCode Asm::Directive_XREF(strref label)
|
|||
}
|
||||
|
||||
// dc.b, dc.w, dc.t, dc.l, ADR, ADRL, bytes, words, long
|
||||
StatusCode Asm::Directive_DC(strref line, int width, strref source_file)
|
||||
StatusCode Asm::Directive_DC(strref line, int width, strref source_file, bool little_endian)
|
||||
{
|
||||
struct EvalContext etx;
|
||||
SetEvalCtxDefaults(etx);
|
||||
|
@ -5401,18 +5497,43 @@ StatusCode Asm::Directive_DC(strref line, int width, strref source_file)
|
|||
StatusCode error = EvalExpression(exp_dc, etx, value);
|
||||
if (error > STATUS_XREF_DEPENDENT)
|
||||
break;
|
||||
else if (error == STATUS_NOT_READY || error == STATUS_XREF_DEPENDENT)
|
||||
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], exp_dc, source_file,
|
||||
width == 1 ? LateEval::LET_BYTE : (width == 2 ? LateEval::LET_ABS_REF : (width == 3 ? LateEval::LET_ABS_L_REF : LateEval::LET_ABS_4_REF)));
|
||||
else if (error == STATUS_RELATIVE_SECTION) {
|
||||
else if (error == STATUS_NOT_READY || error == STATUS_XREF_DEPENDENT) {
|
||||
static LateEval::Type sizes[] = {
|
||||
LateEval::LET_BYTE,
|
||||
LateEval::LET_ABS_REF,
|
||||
LateEval::LET_ABS_L_REF,
|
||||
LateEval::LET_ABS_4_REF
|
||||
};
|
||||
LateEval::Type type = sizes[width - 1];
|
||||
if (!little_endian && width == 2) {
|
||||
type = LateEval::LET_DBL_BYTE;
|
||||
}
|
||||
|
||||
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], exp_dc, source_file, type);
|
||||
} else if (error == STATUS_RELATIVE_SECTION) {
|
||||
value = 0;
|
||||
if (little_endian || width == 1) {
|
||||
CurrSection().AddReloc(lastEvalValue, CurrSection().DataOffset(), lastEvalSection, (int8_t)width, (int8_t)lastEvalShift);
|
||||
} else {
|
||||
// big endian needs 1 reloc for each byte
|
||||
int shift = lastEvalShift + 8 - width * 8;
|
||||
for (int i = 0; i < width; ++i, shift += 8) {
|
||||
CurrSection().AddReloc(lastEvalValue, CurrSection().DataOffset() + i, lastEvalSection, 1, (int8_t)shift);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (little_endian) {
|
||||
uint8_t bytes[4] = {
|
||||
(uint8_t)value, (uint8_t)(value >> 8),
|
||||
(uint8_t)(value >> 16), (uint8_t)(value >> 24) };
|
||||
AddBin(bytes, width);
|
||||
} else {
|
||||
uint8_t bytes[4] = {
|
||||
(uint8_t)(value >> 24), (uint8_t)(value >> 16),
|
||||
(uint8_t)(value >> 8), (uint8_t)value };
|
||||
AddBin(bytes + 4 - width, width);
|
||||
}
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
@ -5655,6 +5776,9 @@ StatusCode Asm::ApplyDirective(AssemblerDirective dir, strref line, strref sourc
|
|||
case AD_WORDS: // words: add words (16 bit values) by comma separated values
|
||||
return Directive_DC(line, 2, source_file);
|
||||
|
||||
case AD_DBL_BYTES: // DDB: Merlin store 2-byte word, big endian format.
|
||||
return Directive_DC(line, 2, source_file, false);
|
||||
|
||||
case AD_ADR: // ADR: MERLIN store 3 byte word
|
||||
return Directive_DC(line, 3, source_file);
|
||||
|
||||
|
@ -5727,7 +5851,8 @@ StatusCode Asm::ApplyDirective(AssemblerDirective dir, strref line, strref sourc
|
|||
}
|
||||
while (line[0] != '"') {
|
||||
strref word = line.get_word_ws();
|
||||
if (word.same_str("petscii") || word.same_str("petscii_shifted")) {
|
||||
if (word.same_str("petscii") || word.same_str("petscii_shifted") ||
|
||||
word.same_str("c64screen")) {
|
||||
text_prefix = line.get_word_ws();
|
||||
line += text_prefix.get_len();
|
||||
line.skip_whitespace();
|
||||
|
@ -6022,7 +6147,7 @@ StatusCode Asm::GetAddressMode(strref line, bool flipXY, uint32_t &validModes, A
|
|||
validModes &= AMM_ZP_REL_X | AMM_ZP_Y_REL | AMM_REL | AMM_ZP_REL | AMM_REL_X | AMM_ZP_REL_L | AMM_ZP_REL_Y_L | AMM_STK_REL_Y | AMM_REL_L;
|
||||
if( line.get_first() == '>' ) { // [>$aaaa]
|
||||
if( c == '[' ) { addrMode = AMB_REL_L; validModes &= AMM_REL_L; expression = block+1; }
|
||||
} else if( line.get_first() == '|' || line.get_first() == '!' && c == '(' ) { // (|$aaaa) or (|$aaaa,x)
|
||||
} else if( line.get_first() == '|' || (line.get_first() == '!' && c == '(' )) { // (|$aaaa) or (|$aaaa,x)
|
||||
strref arg = block.after( ',' ); arg.skip_whitespace();
|
||||
if( arg && ( arg.get_first() == 'x' || arg.get_first() == 'X' ) ) {
|
||||
addrMode = AMB_REL_X; validModes &= AMM_REL_X; expression = block.before( ',' ); }
|
||||
|
@ -6387,22 +6512,32 @@ StatusCode Asm::AddOpcode(strref line, int index, strref source_file) {
|
|||
break;
|
||||
|
||||
case CA_TWO_ARG_BYTES: {
|
||||
// second operand stored first.
|
||||
StatusCode error = STATUS_OK;
|
||||
int value = 0;
|
||||
|
||||
struct EvalContext etx;
|
||||
SetEvalCtxDefaults(etx);
|
||||
etx.pc = CurrSection().GetPC()-1;
|
||||
line.split_token_trim_track_parens(',');
|
||||
error = EvalExpression(line, etx, value);
|
||||
if (error==STATUS_NOT_READY || error == STATUS_XREF_DEPENDENT)
|
||||
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC()-1, scope_address[scope_depth], line, source_file, LateEval::LET_BYTE);
|
||||
else if (error == STATUS_RELATIVE_SECTION) {
|
||||
CurrSection().AddReloc(target_section_offs, CurrSection().DataOffset(), lastEvalSection, 1, lastEvalShift);
|
||||
}
|
||||
|
||||
AddByte(value);
|
||||
}
|
||||
|
||||
if (evalLater)
|
||||
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_BYTE);
|
||||
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC()-2, scope_address[scope_depth], expression, source_file, LateEval::LET_BYTE);
|
||||
else if (error == STATUS_RELATIVE_SECTION) {
|
||||
CurrSection().AddReloc(target_section_offs, CurrSection().DataOffset(), target_section, 1, target_section_shift);
|
||||
}
|
||||
AddByte(value);
|
||||
struct EvalContext etx;
|
||||
SetEvalCtxDefaults(etx);
|
||||
etx.pc = CurrSection().GetPC()-2;
|
||||
line.split_token_trim_track_parens(',');
|
||||
error = EvalExpression(line, etx, value);
|
||||
if (error==STATUS_NOT_READY || error == STATUS_XREF_DEPENDENT)
|
||||
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], line, source_file, LateEval::LET_BYTE);
|
||||
AddByte(value);
|
||||
break;
|
||||
}
|
||||
|
||||
case CA_BRANCH:
|
||||
if (evalLater)
|
||||
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_BRANCH);
|
||||
|
@ -6471,6 +6606,7 @@ StatusCode Asm::BuildLine(strref line) {
|
|||
int start_section = SectionId();
|
||||
int start_address = CurrSection().address;
|
||||
strref code_line = line;
|
||||
const char* data_line = line.get(); // code_line is current line, data_line is where data is generated
|
||||
list_flags = 0;
|
||||
|
||||
while (line && error == STATUS_OK) {
|
||||
|
@ -6539,9 +6675,11 @@ StatusCode Asm::BuildLine(strref line) {
|
|||
line.skip_whitespace();
|
||||
}
|
||||
if (aInstructions[op_idx].type==OT_DIRECTIVE) {
|
||||
data_line = operation.get();
|
||||
error = ApplyDirective((AssemblerDirective)aInstructions[op_idx].index, line, contextStack.curr().source_file);
|
||||
list_flags |= ListLine::KEYWORD;
|
||||
} else if (ConditionalAsm() && aInstructions[op_idx].type == OT_MNEMONIC) {
|
||||
data_line = operation.get();
|
||||
error = AddOpcode(line, aInstructions[op_idx].index, contextStack.curr().source_file);
|
||||
list_flags |= ListLine::MNEMONIC;
|
||||
}
|
||||
|
@ -6631,29 +6769,57 @@ StatusCode Asm::BuildLine(strref line) {
|
|||
}
|
||||
}
|
||||
// update listing
|
||||
if (error == STATUS_OK && list_assembly) {
|
||||
if (error == STATUS_OK) {
|
||||
if (SectionId() == start_section) {
|
||||
Section &curr = CurrSection();
|
||||
if (list_assembly) {
|
||||
if (!curr.pListing) { curr.pListing = new Listing; }
|
||||
if (curr.pListing && curr.pListing->size()==curr.pListing->capacity()) {
|
||||
curr.pListing->reserve(curr.pListing->size()+256);
|
||||
}
|
||||
if (((list_flags & (ListLine::KEYWORD | ListLine::CYCLES_START | ListLine::CYCLES_STOP)) ||
|
||||
(curr.address != start_address && curr.size())) && !curr.IsDummySection()) {
|
||||
struct ListLine lst;
|
||||
lst.address = start_address - curr.start_address;
|
||||
lst.size = curr.address - start_address;
|
||||
lst.code = contextStack.curr().source_file;
|
||||
lst.column = (uint16_t)(data_line - code_line.get());
|
||||
lst.source_name = contextStack.curr().source_name;
|
||||
lst.line_offs = int(code_line.get() - lst.code.get());
|
||||
lst.flags = list_flags;
|
||||
curr.pListing->push_back(lst);
|
||||
}
|
||||
}
|
||||
if (src_debug) {
|
||||
if (curr.address != start_address && curr.size()) {
|
||||
AddSrcDbg(start_address, SourceDebugType::Code, data_line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
void Asm::AddSrcDbg(int address, SourceDebugType type, const char* text)
|
||||
{
|
||||
SourceDebugEntry entry;
|
||||
Section& curr = CurrSection();
|
||||
if (!curr.pSrcDbg) { curr.pSrcDbg = new SourceDebug; }
|
||||
|
||||
entry.address = address - curr.start_address;
|
||||
entry.size = curr.address - address;
|
||||
entry.type = (int)type;
|
||||
|
||||
size_t sf = 0, nsf = source_files.size();
|
||||
strref src = contextStack.curr().source_name;
|
||||
for (; sf < nsf; ++sf) {
|
||||
if (src.same_str_case(source_files[sf])) { break; }
|
||||
}
|
||||
if (sf == nsf) {
|
||||
source_files.push_back(StringCopy(src));
|
||||
}
|
||||
entry.source_file_index = (int)sf;
|
||||
entry.source_file_offset = (int)(text - contextStack.curr().source_file.get());
|
||||
curr.pSrcDbg->push_back(entry);
|
||||
}
|
||||
|
||||
// Build a segment of code (file or macro)
|
||||
StatusCode Asm::BuildSegment() {
|
||||
StatusCode error = STATUS_OK;
|
||||
|
@ -6783,7 +6949,7 @@ bool Asm::ListTassStyle( strref filename ) {
|
|||
} else if (am==AMB_ABS_L||am==AMB_ABS_L_X) {
|
||||
out.sprintf_append(fmt, opcode_table[op].instr, buf[1]|(buf[2]<<8)|(buf[3]<<16));
|
||||
} else if (am==AMB_BLK_MOV) {
|
||||
out.sprintf_append(fmt, opcode_table[op].instr, buf[1], buf[2]);
|
||||
out.sprintf_append(fmt, opcode_table[op].instr, buf[2], buf[1]);
|
||||
} else if (am==AMB_IMM && lst.size==3) {
|
||||
out.sprintf_append("%s #$%04x", opcode_table[op].instr, buf[1]|(buf[2]<<8));
|
||||
} else {
|
||||
|
@ -6811,6 +6977,100 @@ bool Asm::ListTassStyle( strref filename ) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Asm::SourceDebugExport(strref filename) {
|
||||
FILE* f = stdout;
|
||||
bool opened = false;
|
||||
if (filename) {
|
||||
f = fopen(strown<512>(filename).c_str(), "w");
|
||||
if (!f) { return false; }
|
||||
opened = true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<strovl> source_code; source_code.reserve(source_files.size());
|
||||
|
||||
fprintf(f, "<C64debugger version=\"1.0\">\n\t<Sources values=\"INDEX,FILE\">\n");
|
||||
for (size_t i = 0, n = source_files.size(); i < n; ++i) {
|
||||
fprintf(f, "\t\t%d,%s\n", (int)i+1, source_files[i]);
|
||||
|
||||
size_t size = 0;
|
||||
char* src = LoadText(source_files[i], size);
|
||||
source_code.push_back(strovl(src, (strl_t)size, (strl_t)size));
|
||||
}
|
||||
fprintf(f, "\t</Sources>\n\n");
|
||||
|
||||
for (size_t i = 0, n = allSections.size(); i < n; ++i) {
|
||||
Section& s = allSections[i];
|
||||
if (s.pSrcDbg && s.pSrcDbg->size()) {
|
||||
fprintf(f, "\t<Segment name=\"" STRREF_FMT "\" dest=\"\" values=\"START,END,FILE_IDX,LINE1,COL1,LINE2,COL2\">\n\t\t<Block name=\"Unnamed\">\n",
|
||||
STRREF_ARG(s.name));
|
||||
for (size_t d = 0, nd = s.pSrcDbg->size(); d < nd; ++d) {
|
||||
SourceDebugEntry& e = s.pSrcDbg->at(d);
|
||||
int line = 0, col0 = 0, col1 = 0;
|
||||
if ((e.source_file_index) < source_code.size()) {
|
||||
strref src = source_code[e.source_file_index].get_strref();
|
||||
if (src.get_len() > strl_t(e.source_file_offset)) {
|
||||
line = strref(src.get(), e.source_file_offset).count_lines();
|
||||
strl_t offs = e.source_file_offset;
|
||||
while (src.get_at(offs) != 0x0a && src.get_at(offs) != 0x0d && offs) { --offs; ++col0; }
|
||||
col1 = col0;
|
||||
offs = e.source_file_offset;
|
||||
while (src.get_at(offs) != 0x0a && src.get_at(offs) != 0x0d && offs<src.get_len()) { ++offs; ++col1; }
|
||||
}
|
||||
}
|
||||
fprintf(f, "\t\t\t$%04x,$%04x,%d,%d,%d,%d,%d\n",
|
||||
e.address+s.start_address, e.address+e.size+s.start_address-1, e.source_file_index+1,
|
||||
line+1, col0 ? (col0-1) : 0, line+1, col1 );
|
||||
}
|
||||
fprintf(f, "\t\t</Block>\n\t</Segment>\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(f, "\t<Labels values=\"SEGMENT,ADDRESS,NAME,START,END,FILE_IDX,LINE1,COL1,LINE2,COL2\">\n");
|
||||
for (MapSymbolArray::iterator i = map.begin(); i != map.end(); ++i) {
|
||||
if (i->name.same_str("debugbreak")) { continue; }
|
||||
uint32_t value = (uint32_t)i->value;
|
||||
strref sectName;
|
||||
int16_t section = i->section;
|
||||
int16_t orig_section = i->orig_section;
|
||||
if (size_t(section) < allSections.size()) {
|
||||
value += allSections[section].start_address;
|
||||
}
|
||||
if (size_t(orig_section) < allSections.size()) {
|
||||
sectName = allSections[orig_section].name;
|
||||
}
|
||||
fprintf(f, "\t\t" STRREF_FMT ",$%04x," STRREF_FMT ",0,0,0,0,0\n", STRREF_ARG(sectName), value, STRREF_ARG(i->name));
|
||||
}
|
||||
fprintf(f, "\t</Labels>\n\n");
|
||||
|
||||
fprintf(f, "\t<Breakpoints values=\"SEGMENT,ADDRESS,ARGUMENT\">\n");
|
||||
for (MapSymbolArray::iterator i = map.begin(); i != map.end(); ++i) {
|
||||
if (i->name.same_str("debugbreak")) {
|
||||
uint32_t value = (uint32_t)i->value;
|
||||
strref sectName;
|
||||
uint16_t section = i->section;
|
||||
if (size_t(section) < allSections.size()) {
|
||||
value += allSections[section].start_address;
|
||||
sectName = allSections[section].name;
|
||||
}
|
||||
fprintf(f, "\t\t" STRREF_FMT ",$%04x,\n", STRREF_ARG(sectName), value);
|
||||
}
|
||||
}
|
||||
fprintf(f, "\t</Breakpoints>\n\n");
|
||||
|
||||
fprintf(f, "\t<Watchpoints values=\"SEGMENT,ADDRESS1,ADDRESS2,ARGUMENT\">\n");
|
||||
fprintf(f, "\t</Watchpoints>\n\n");
|
||||
|
||||
fprintf(f, "</C64debugger>\n");
|
||||
fclose(f);
|
||||
|
||||
for (size_t i = 0, n = source_code.size(); i < n; ++i) {
|
||||
if (source_code[i].get()) { free(source_code[i].charstr()); }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Asm::List(strref filename) {
|
||||
FILE *f = stdout;
|
||||
bool opened = false;
|
||||
|
@ -6980,7 +7240,7 @@ bool Asm::List(strref filename) {
|
|||
} else if (am==AMB_ABS_L||am==AMB_ABS_L_X) {
|
||||
out.sprintf_append(fmt, opcode_table[op].instr, buf[1]|(buf[2]<<8)|(buf[3]<<16));
|
||||
} else if (am==AMB_BLK_MOV) {
|
||||
out.sprintf_append(fmt, opcode_table[op].instr, buf[1], buf[2]);
|
||||
out.sprintf_append(fmt, opcode_table[op].instr, buf[2], buf[1]);
|
||||
} else if (am==AMB_IMM && lst.size==3) {
|
||||
out.sprintf_append("%s #$%04x", opcode_table[op].instr, buf[1]|(buf[2]<<8));
|
||||
} else {
|
||||
|
@ -7109,7 +7369,7 @@ void Asm::Assemble(strref source, strref filename, bool obj_target) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
PrintError(&contextStack.curr() ?
|
||||
PrintError(contextStack.has_work() ?
|
||||
contextStack.curr().read_source.get_line() : strref(), error);
|
||||
}
|
||||
}
|
||||
|
@ -7128,6 +7388,7 @@ struct ObjFileHeader {
|
|||
int16_t late_evals;
|
||||
int16_t map_symbols;
|
||||
uint32_t stringdata;
|
||||
uint32_t srcdebug;
|
||||
int bindata;
|
||||
};
|
||||
|
||||
|
@ -7147,6 +7408,7 @@ struct ObjFileSection {
|
|||
int end_address; // address size
|
||||
int output_size; // assembled binary size
|
||||
int align_address;
|
||||
int srcdebug_count; // how many addresses included in debugger listing
|
||||
int16_t next_group; // next section of group
|
||||
int16_t first_group; // first section of group
|
||||
int16_t relocs;
|
||||
|
@ -7154,6 +7416,10 @@ struct ObjFileSection {
|
|||
int8_t flags;
|
||||
};
|
||||
|
||||
struct ObjFileSource {
|
||||
struct ObjFileStr file;
|
||||
};
|
||||
|
||||
struct ObjFileReloc {
|
||||
int base_value;
|
||||
int section_offset;
|
||||
|
@ -7190,10 +7456,27 @@ struct ObjFileLateEval {
|
|||
struct ObjFileMapSymbol {
|
||||
struct ObjFileStr name; // symbol name
|
||||
int value;
|
||||
int16_t section;
|
||||
int16_t section; // address relative to this section
|
||||
int16_t orig_section; // seciton label originated from
|
||||
bool local; // local labels are probably needed
|
||||
};
|
||||
|
||||
// this struct is follwed by numSources x ObjFileStr
|
||||
struct ObjFileSourceList {
|
||||
uint32_t numSources;
|
||||
ObjFileStr sourceFile[1];
|
||||
};
|
||||
|
||||
// after that one long array of all sections worth of source references
|
||||
struct ObjFileSrcDbg {
|
||||
uint16_t addr; // relative to section
|
||||
uint16_t src_idx;
|
||||
uint16_t size;
|
||||
uint16_t _pad;
|
||||
uint32_t file_offs; // byte offset into file to row/column where op starts1
|
||||
};
|
||||
|
||||
|
||||
// Simple string pool, converts strref strings to zero terminated strings and returns the offset to the string in the pool.
|
||||
static int _AddStrPool(const strref str, pairArray<uint32_t, int> *pLookup, char **strPool, uint32_t &strPoolSize, uint32_t &strPoolCap) {
|
||||
if (!str.get()||!str.get_len()) { return -1; } // empty string
|
||||
|
@ -7263,6 +7546,7 @@ StatusCode Asm::WriteObjectFile(strref filename) {
|
|||
hdr.late_evals = (int16_t)lateEval.size();
|
||||
hdr.map_symbols = (int16_t)map.size();
|
||||
hdr.stringdata = 0;
|
||||
hdr.srcdebug = 0;
|
||||
|
||||
// labels don't include XREF labels
|
||||
hdr.labels = 0;
|
||||
|
@ -7283,7 +7567,7 @@ StatusCode Asm::WriteObjectFile(strref filename) {
|
|||
char *stringPool = nullptr;
|
||||
uint32_t stringPoolCap = 0;
|
||||
pairArray<uint32_t, int> stringArray;
|
||||
stringArray.reserve(hdr.labels * 2 + hdr.sections + hdr.late_evals*2);
|
||||
stringArray.reserve(hdr.labels * 2 + hdr.sections + hdr.late_evals*2 + (uint32_t)source_files.size());
|
||||
|
||||
struct ObjFileSection *aSects = hdr.sections ? (struct ObjFileSection*)calloc(hdr.sections, sizeof(struct ObjFileSection)) : nullptr;
|
||||
struct ObjFileReloc *aRelocs = hdr.relocs ? (struct ObjFileReloc*)calloc(hdr.relocs, sizeof(struct ObjFileReloc)) : nullptr;
|
||||
|
@ -7301,11 +7585,11 @@ StatusCode Asm::WriteObjectFile(strref filename) {
|
|||
}
|
||||
|
||||
sect = 0;
|
||||
uint32_t srcDbgEntries = 0;
|
||||
// write out sections and relocs
|
||||
if (hdr.sections) {
|
||||
for (std::vector<Section>::iterator si = allSections.begin(); si!=allSections.end(); ++si) {
|
||||
if (si->type == ST_REMOVED)
|
||||
continue;
|
||||
if (si->type == ST_REMOVED) { continue; }
|
||||
struct ObjFileSection &s = aSects[sect++];
|
||||
s.name.offs = _AddStrPool(si->name, &stringArray, &stringPool, hdr.stringdata, stringPoolCap);
|
||||
s.exp_app.offs = _AddStrPool(si->export_append, &stringArray, &stringPool, hdr.stringdata, stringPoolCap);
|
||||
|
@ -7314,6 +7598,8 @@ StatusCode Asm::WriteObjectFile(strref filename) {
|
|||
s.next_group = si->next_group >= 0 ? aRemapSects[si->next_group] : -1;
|
||||
s.first_group = si->first_group >= 0 ? aRemapSects[si->first_group] : -1;
|
||||
s.relocs = si->pRelocs ? (int16_t)(si->pRelocs->size()) : 0;
|
||||
s.srcdebug_count = si->pSrcDbg ? (int)si->pSrcDbg->size() : 0;
|
||||
srcDbgEntries += s.srcdebug_count;
|
||||
s.start_address = si->start_address;
|
||||
s.end_address = si->address;
|
||||
s.type = si->type;
|
||||
|
@ -7335,6 +7621,25 @@ StatusCode Asm::WriteObjectFile(strref filename) {
|
|||
}
|
||||
hdr.sections = (int16_t)sect;
|
||||
|
||||
struct ObjFileSrcDbg* srcLines = srcDbgEntries ? (ObjFileSrcDbg*)calloc(1, sizeof(ObjFileSrcDbg) * srcDbgEntries) : nullptr;
|
||||
if (srcLines) {
|
||||
size_t srcDbgIdx = 0;
|
||||
for (std::vector<Section>::iterator si = allSections.begin(); si != allSections.end(); ++si) {
|
||||
if (si->type == ST_REMOVED) { continue; }
|
||||
if (si->pSrcDbg && si->pSrcDbg->size()) {
|
||||
for (size_t src = 0, nsrc = si->pSrcDbg->size(); src < nsrc; ++src) {
|
||||
SourceDebugEntry& entry = si->pSrcDbg->at(src);
|
||||
ObjFileSrcDbg& ref = srcLines[srcDbgIdx++];
|
||||
ref.addr = entry.address;
|
||||
ref.src_idx = entry.source_file_index;
|
||||
ref.size = entry.size;
|
||||
ref.file_offs = entry.source_file_offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(srcDbgIdx == srcDbgEntries);
|
||||
}
|
||||
|
||||
// write out labels
|
||||
if (hdr.labels) {
|
||||
for (uint32_t li = 0; li<labels.count(); li++) {
|
||||
|
@ -7398,9 +7703,21 @@ StatusCode Asm::WriteObjectFile(strref filename) {
|
|||
ms.value = mi->value;
|
||||
ms.local = mi->local;
|
||||
ms.section = mi->section >= 0 ? aRemapSects[mi->section] : -1;
|
||||
ms.orig_section = mi->orig_section >= 0 ? aRemapSects[mi->orig_section] : -1;
|
||||
}
|
||||
}
|
||||
|
||||
struct ObjFileSourceList* sourceList = nullptr;
|
||||
if (source_files.size() && srcLines) {
|
||||
sourceList = (struct ObjFileSourceList*)calloc(1, sizeof(ObjFileSourceList) + sizeof(ObjFileStr) * (source_files.size() - 1));
|
||||
sourceList->numSources = (uint32_t)source_files.size();
|
||||
for (size_t src = 0, nsrc = source_files.size(); src < nsrc; ++src) {
|
||||
sourceList->sourceFile[src].offs = _AddStrPool(strref(source_files[src]), &stringArray, &stringPool, hdr.stringdata, stringPoolCap);
|
||||
}
|
||||
}
|
||||
|
||||
hdr.srcdebug = srcDbgEntries;
|
||||
|
||||
// write out the file
|
||||
fwrite(&hdr, sizeof(hdr), 1, f);
|
||||
fwrite(aSects, sizeof(aSects[0]), sect, f);
|
||||
|
@ -7414,6 +7731,12 @@ StatusCode Asm::WriteObjectFile(strref filename) {
|
|||
fwrite(si->output, si->size(), 1, f);
|
||||
}
|
||||
}
|
||||
if (sourceList) {
|
||||
fwrite(sourceList, sizeof(ObjFileSourceList) + sizeof(ObjFileStr) * (source_files.size() - 1), 1, f);
|
||||
fwrite(srcLines, sizeof(ObjFileSrcDbg) * srcDbgEntries, 1, f);
|
||||
}
|
||||
|
||||
|
||||
// done with I/O
|
||||
fclose(f);
|
||||
if (aRemapSects) { free(aRemapSects); }
|
||||
|
@ -7442,6 +7765,14 @@ StatusCode Asm::ReadObjectFile(strref filename, int link_to_section)
|
|||
hdr.relocs * sizeof(struct ObjFileReloc) + hdr.labels * sizeof(struct ObjFileLabel) +
|
||||
hdr.late_evals * sizeof(struct ObjFileLateEval) +
|
||||
hdr.map_symbols * sizeof(struct ObjFileMapSymbol) + hdr.stringdata + hdr.bindata;
|
||||
const struct ObjFileSourceList* pSrcDbgInfo = hdr.srcdebug ? (struct ObjFileSourceList*)(data + sum) : nullptr;
|
||||
const struct ObjFileSrcDbg* pSrcDbgEntry = pSrcDbgInfo ? (const struct ObjFileSrcDbg*)(pSrcDbgInfo->sourceFile + pSrcDbgInfo->numSources) : nullptr;
|
||||
|
||||
if (pSrcDbgInfo) {
|
||||
sum += sizeof(ObjFileSourceList) + (pSrcDbgInfo->numSources - 1) * sizeof(ObjFileStr);
|
||||
sum += sizeof(ObjFileSrcDbg) * hdr.srcdebug;
|
||||
}
|
||||
|
||||
if (hdr.id == 0x7836 && sum == size) {
|
||||
struct ObjFileSection *aSect = (struct ObjFileSection*)(&hdr + 1);
|
||||
struct ObjFileReloc *aReloc = (struct ObjFileReloc*)(aSect + hdr.sections);
|
||||
|
@ -7455,6 +7786,23 @@ StatusCode Asm::ReadObjectFile(strref filename, int link_to_section)
|
|||
memcpy(str_pool, str_orig, hdr.stringdata);
|
||||
loadedData.push_back(str_pool);
|
||||
|
||||
// source files
|
||||
std::vector<size_t> source_file_remap;
|
||||
if (pSrcDbgInfo) {
|
||||
source_file_remap.reserve(pSrcDbgInfo->numSources);
|
||||
for (size_t s = 0, n = pSrcDbgInfo->numSources; s < n; ++s) {
|
||||
strref source_file(str_pool + pSrcDbgInfo->sourceFile[s].offs);
|
||||
size_t i = 0, sz = source_files.size();
|
||||
for (; i < sz; ++i) {
|
||||
if (source_file.same_str(source_files[i])) { break; }
|
||||
}
|
||||
if (i == sz) {
|
||||
source_files.push_back(StringCopy(source_file));
|
||||
}
|
||||
source_file_remap.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
int prevSection = SectionId();
|
||||
int16_t *aSctRmp = (int16_t*)malloc(hdr.sections * sizeof(int16_t));
|
||||
int last_linked_section = link_to_section;
|
||||
|
@ -7499,6 +7847,19 @@ StatusCode Asm::ReadObjectFile(strref filename, int link_to_section)
|
|||
s.first_group = allSections[last_linked_section].first_group >=0 ? allSections[last_linked_section].first_group : last_linked_section;
|
||||
last_linked_section = SectionId();
|
||||
}
|
||||
// add source debug entries from object file
|
||||
if (aSect[si].srcdebug_count) {
|
||||
if (!s.pSrcDbg) { s.pSrcDbg = new SourceDebug; }
|
||||
for (int sd = 0, nsd = aSect[si].srcdebug_count; sd < nsd; ++sd) {
|
||||
SourceDebugEntry entry;
|
||||
entry.address = pSrcDbgEntry->addr;
|
||||
entry.size = pSrcDbgEntry->size;
|
||||
entry.source_file_index = (int)source_file_remap[pSrcDbgEntry->src_idx];
|
||||
entry.source_file_offset = pSrcDbgEntry->file_offs;
|
||||
s.pSrcDbg->push_back(entry);
|
||||
++pSrcDbgEntry;
|
||||
}
|
||||
}
|
||||
}
|
||||
aSctRmp[si] = (int16_t)allSections.size()-1;
|
||||
}
|
||||
|
@ -7527,6 +7888,7 @@ StatusCode Asm::ReadObjectFile(strref filename, int link_to_section)
|
|||
MapSymbol sym;
|
||||
sym.name = m.name.offs>=0 ? strref(str_pool + m.name.offs) : strref();
|
||||
sym.section = m.section >=0 ? aSctRmp[m.section] : m.section;
|
||||
sym.orig_section = m.orig_section >= 0 ? aSctRmp[m.orig_section] : m.orig_section;
|
||||
sym.value = m.value;
|
||||
sym.local = m.local;
|
||||
map.push_back(sym);
|
||||
|
@ -7881,6 +8243,7 @@ int main(int argc, char **argv) {
|
|||
const char *sym_file = nullptr, *vs_file = nullptr, *cmdarg_tass_labels_file = nullptr;
|
||||
strref list_file, allinstr_file;
|
||||
strref tass_list_file;
|
||||
strref srcdebug_file;
|
||||
for (int a = 1; a<argc; a++) {
|
||||
if (argv[a][0]=='-') {
|
||||
strref arg(argv[a]+1);
|
||||
|
@ -7924,7 +8287,10 @@ int main(int argc, char **argv) {
|
|||
assembler.list_assembly = true;
|
||||
list_output = true;
|
||||
list_file = arg.after('=');
|
||||
} else if (arg.has_prefix(cmdarg_tass_listing)&&(arg.get_len()==cmdarg_listing.get_len()||arg[cmdarg_listing.get_len()]=='=')) {
|
||||
} else if (arg.has_prefix(cmdarg_srcdebug) && (arg.get_len() == cmdarg_srcdebug.get_len() || arg[cmdarg_srcdebug.get_len()] == '=')) {
|
||||
assembler.src_debug = true;
|
||||
srcdebug_file = arg.after('=');
|
||||
} else if (arg.has_prefix(cmdarg_tass_listing)&&(arg.get_len()== cmdarg_tass_listing.get_len()||arg[cmdarg_tass_listing.get_len()]=='=')) {
|
||||
assembler.list_assembly = true;
|
||||
tass_list_output = true;
|
||||
tass_list_file = arg.after( '=' );
|
||||
|
@ -7996,6 +8362,7 @@ int main(int argc, char **argv) {
|
|||
" * -sym (file.sym) : symbol file\n"
|
||||
" * -lst / -lst = (file.lst) : generate disassembly text from result(file or stdout)\n"
|
||||
" * -opcodes / -opcodes=(file.s) : dump all available opcodes(file or stdout)\n"
|
||||
" * -srcdbg / -srcdbg=(file.dbg) : generate a source level debugging file for object files or linked files"
|
||||
" * -sect: display sections loaded and built\n"
|
||||
" * -vice (file.vs) : export a vice symbol file\n"
|
||||
" * -merlin: use Merlin syntax\n"
|
||||
|
@ -8082,11 +8449,11 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
// listing after export since addresses are now resolved
|
||||
if ( list_output )
|
||||
assembler.List(list_file);
|
||||
if (list_output) { assembler.List(list_file); }
|
||||
|
||||
if( tass_list_output )
|
||||
assembler.ListTassStyle(tass_list_file);
|
||||
if (srcdebug_file) { assembler.SourceDebugExport(srcdebug_file); }
|
||||
|
||||
if (tass_list_output) { assembler.ListTassStyle(tass_list_file); }
|
||||
|
||||
// export .sym file
|
||||
if (sym_file && !srcname.same_str(sym_file) && !assembler.map.empty()) {
|
||||
|
@ -8094,7 +8461,9 @@ int main(int argc, char **argv) {
|
|||
bool wasLocal = false;
|
||||
for (MapSymbolArray::iterator i = assembler.map.begin(); i!=assembler.map.end(); ++i) {
|
||||
uint32_t value = (uint32_t)i->value;
|
||||
if (size_t(i->section) < assembler.allSections.size()) { value += assembler.allSections[i->section].start_address; }
|
||||
if (size_t(i->section) < assembler.allSections.size()) {
|
||||
value += assembler.allSections[i->section].start_address;
|
||||
}
|
||||
fprintf(f, "%s.label " STRREF_FMT " = $%04x", wasLocal==i->local ? "\n" :
|
||||
(i->local ? " {\n" : "\n}\n"), STRREF_ARG(i->name), value);
|
||||
wasLocal = i->local;
|
||||
|
@ -8131,15 +8500,12 @@ int main(int argc, char **argv) {
|
|||
strown<256> line;
|
||||
line.append( i->name );
|
||||
line.sprintf_append( "\t= $%04x\n", value);
|
||||
fprintf(f, line.c_str());
|
||||
fputs(line.c_str(), f);
|
||||
}
|
||||
}
|
||||
fclose( f );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
// free some memory
|
||||
assembler.Cleanup();
|
||||
|
|
Loading…
Reference in New Issue
Block a user