RetroLinker
Linker for several 8-bit, 16-bit and 32-bit formats
Loading...
Searching...
No Matches
cpm68k.h
1#ifndef CPM68K_H
2#define CPM68K_H
3
4#include <map>
5#include <set>
6#include <string>
7#include "../common.h"
8#include "../linker/module.h"
9#include "../linker/options.h"
10#include "../linker/reader.h"
11#include "../linker/segment.h"
12#include "../linker/segment_manager.h"
13#include "../linker/writer.h"
14#include "../dumper/dumper.h"
15
16namespace DigitalResearch
17{
18 namespace CDOS
19 {
20 template <typename SizeType>
21 offset_t MeasureRelocations(const std::map<uint32_t, SizeType>& relocations)
22 {
23 /* TODO: test */
24 offset_t count = 0;
25 offset_t last_relocation = 0;
26 for(auto it : relocations)
27 {
28 offset_t difference = it.first - last_relocation;
29 if(difference != 0 && difference <= 0x7C)
30 {
31 count += 1;
32 }
33 else if(difference < 0x100)
34 {
35 count += 2;
36 }
37 else if(difference < 0x10000)
38 {
39 count += 3;
40 }
41 else
42 {
43 count += 5;
44 }
45 }
46 return count;
47 }
48
49 template <typename SizeType>
50 void WriteRelocations(const std::shared_ptr<Linker::Writer>& wr, const std::map<uint32_t, SizeType>& relocations)
51 {
52 /* TODO: test */
53 offset_t last_relocation = 0;
54 for(auto it : relocations)
55 {
56 offset_t difference = it.first - last_relocation;
57 uint8_t highbit = it.second/*.size*/ == 2 ? 0x80 : 0x00;
58 if(difference != 0 && difference <= 0x7C)
59 {
60 wr->WriteWord(1, highbit | difference);
61 }
62 else if(difference < 0x100)
63 {
64 wr->WriteWord(1, highbit | 0x7D);
65 wr->WriteWord(1, difference);
66 }
67 else if(difference < 0x10000)
68 {
69 wr->WriteWord(1, highbit | 0x7E);
70 wr->WriteWord(2, difference);
71 }
72 else
73 {
74 wr->WriteWord(1, highbit | 0x7F);
75 wr->WriteWord(4, difference);
76 }
77 last_relocation = it.first;
78 }
79 wr->WriteWord(1, 0);
80 }
81
82 template <typename SizeType, typename Format>
83 void ReadRelocations(const std::shared_ptr<Linker::Reader>& rd, std::map<uint32_t, SizeType>& relocations, const Format& format)
84 {
85 /* TODO: test */
86 offset_t offset = 0;
87 while(true)
88 {
89 uint8_t byte = rd->ReadUnsigned(1);
90 size_t size = (byte & 0x80) ? 2 : 4;
91 byte &= 0x7F;
92 if(byte == 0)
93 {
94 break;
95 }
96 else if(byte <= 0x7C)
97 {
98 offset += byte;
99 }
100 else if(byte == 0x7D)
101 {
102 offset += rd->ReadUnsigned(1);
103 }
104 else if(byte == 0x7E)
105 {
106 offset += rd->ReadUnsigned(2);
107 }
108 else /*if(byte == 0x7F)*/
109 {
110 offset += rd->ReadUnsigned(4);
111 }
112 relocations[offset] = SizeType::Create(size, offset, format);
113 }
114 }
115 }
116
128 {
129 public:
130 /* * * General members * * */
131
136 {
148 MAGIC_CRUNCHED, /* Concurrent DOS 68K only */
149 };
150
152 char signature[2] = { 0x60, 0x1A };
153
157 uint32_t code_size = 0;
161 uint32_t data_size = 0;
165 uint32_t bss_size = 0;
169 uint32_t symbol_table_size = 0;
173 uint32_t stack_size = 0;
174
178 uint32_t code_address = 0;
182 uint32_t program_flags = 0; /* TODO: make parameter */
183
191 uint32_t data_address = 0;
195 uint32_t bss_address = 0;
199 offset_t file_size = 0;
200
204 std::shared_ptr<Linker::Contents> code = nullptr;
208 std::shared_ptr<Linker::Contents> data = nullptr;
209
210 /* filled in automatically */
212 {
216 size_t size;
220 unsigned segment;
221 operator size_t() const;
222
223 static Relocation Create(size_t size, uint32_t offset, const CPM68KFormat& format);
224 };
228 std::map<uint32_t, Relocation> relocations;
229
230 struct Symbol
231 {
232 std::string name;
233 enum symbol_type
234 {
235 LIBRARY_START = 0x0040,
236 OBJECT_START = 0x0080,
237 BSS_BASED = 0x0100,
238 TEXT_BASED = 0x0200,
239 DATA_BASED = 0x0400,
240 EXTERNAL = 0x0800,
241 REGISTER = 0x1000,
242 GLOBAL = 0x2000,
243 EQUATED = 0x4000,
244 DEFINED = 0x8000,
245 };
246 uint16_t type;
247 uint32_t value;
248
249 static Symbol ReadFile(const std::shared_ptr<Linker::Reader>& rd);
250 void WriteFile(const std::shared_ptr<Linker::Writer>& wr) const;
251 };
252 std::vector<Symbol> symbols;
253
254 magic_type GetSignature() const;
255
256 void SetSignature(magic_type magic);
257
288
293
294 void Clear() override;
295
297 : system(system)
298 {
299 }
300
301 CPM68KFormat(system_type system, magic_type magic)
302 : system(system)
303 {
304 SetSignature(magic);
305 }
306
307 void ReadFile(const std::shared_ptr<Linker::Reader>& rd) override;
308
309 offset_t MeasureRelocations() const;
310
311 offset_t ImageSize() const override;
312
314 offset_t WriteFile(const std::shared_ptr<Linker::Writer>& wr) const override;
315
316 void Dump(Dumper::Dumper& dump) const override;
317
318 void CalculateValues() override;
319
320 /* * * Writer members * * */
321
323 {
324 public:
325 Linker::Option<bool> noreloc{"noreloc", "Suppress generating relocations"};
326 Linker::Option<bool> reloc{"reloc", "Force relocation generation"};
327 // TODO: make stack size a parameter (for Concurrent DOS 68K)
328 // TODO: make parameters for system and format type
329
331 {
332 InitializeFields(noreloc, reloc);
333 }
334 };
335
340
342 std::shared_ptr<Linker::Segment> bss_segment;
344 std::shared_ptr<Linker::Segment> stack_segment;
345
347 std::shared_ptr<Linker::Segment> CodeSegment();
348 std::shared_ptr<const Linker::Segment> CodeSegment() const;
349
351 std::shared_ptr<Linker::Segment> DataSegment();
352 std::shared_ptr<const Linker::Segment> DataSegment() const;
353
354 unsigned FormatAdditionalSectionFlags(std::string section_name) const override;
355
356 static std::vector<Linker::OptionDescription<void> *> ParameterNames;
357 std::vector<Linker::OptionDescription<void> *> GetLinkerScriptParameterNames() override;
358
359 std::shared_ptr<Linker::OptionCollector> GetOptions() override;
360
361 void SetOptions(std::map<std::string, std::string>& options) override;
362
363 void OnNewSegment(std::shared_ptr<Linker::Segment> segment) override;
364
365 void CreateDefaultSegments();
366
367 std::unique_ptr<Script::List> GetScript(Linker::Module& module);
368
369 void Link(Linker::Module& module);
370
371 void ProcessModule(Linker::Module& module) override;
372
373 void GenerateFile(std::string filename, Linker::Module& module) override;
374
376 std::string GetDefaultExtension(Linker::Module& module, std::string filename) const override;
377 };
378
379}
380
381#endif /* CPM68K_H */
The native executable format for the Motorola 68000 port of CP/M.
Definition cpm68k.h:128
void GenerateFile(std::string filename, Linker::Module &module) override
The main function that handles processing, calculating and generating the final image.
Definition cpm68k.cc:1028
offset_t file_size
Size of entire file, not used for generation.
Definition cpm68k.h:199
void OnNewSegment(std::shared_ptr< Linker::Segment > segment) override
Callback function when allocating a new segment When the linker script runs, it creates segments cons...
Definition cpm68k.cc:764
uint32_t stack_size
Size of the stack segment. Only used by Concurrent DOS 68K.
Definition cpm68k.h:173
uint32_t code_address
Load address of the code/text segment. Not used by GEMDOS which stores the program flags at this offs...
Definition cpm68k.h:178
std::shared_ptr< Linker::OptionCollector > GetOptions() override
Returns object containing a sequence of option fields provided with the -S command line flag.
Definition cpm68k.cc:688
std::shared_ptr< Linker::Segment > bss_segment
Segment to collect bss.
Definition cpm68k.h:342
uint32_t bss_size
Size of the uninitialized data (bss) segment. Human68k includes the stack in it.
Definition cpm68k.h:165
std::string GetDefaultExtension(Linker::Module &module, std::string filename) const override
Appends a default extension to the filename.
Definition cpm68k.cc:1050
std::shared_ptr< Linker::Segment > CodeSegment()
Return code segment (if it exists)
Definition cpm68k.cc:640
uint32_t program_flags
Program flags, used by GEMDOS.
Definition cpm68k.h:182
uint32_t bss_address
Load address of the uninitialized data (bss) segment. Only relevant for non-contiguous executables (C...
Definition cpm68k.h:195
std::map< uint32_t, Relocation > relocations
Relocations, not used for Human68k.
Definition cpm68k.h:228
bool option_no_relocation
Makes sure no relocations are placed into the output file.
Definition cpm68k.h:339
uint16_t relocations_suppressed
Set to a non-0 value when relocations are suppressed. Typically this can be 1, but Human68k specifica...
Definition cpm68k.h:187
std::shared_ptr< Linker::Contents > data
Storage for data segment.
Definition cpm68k.h:208
magic_type
Represents the magic number at the beginning of the executable file.
Definition cpm68k.h:136
@ MAGIC_CONTIGUOUS
Contiguous executables (magic value 0x601A in big endian) must load the code, data,...
Definition cpm68k.h:140
@ MAGIC_CRUNCHED
Contiguous executables with crunched relocations (magic value 0x601C in big endian),...
Definition cpm68k.h:148
@ MAGIC_NONCONTIGUOUS
Non-contiguous executables (magic value 0x601B in big endian) can load the code, data,...
Definition cpm68k.h:144
offset_t WriteFile(const std::shared_ptr< Linker::Writer > &wr) const override
Stores data in memory to file.
Definition cpm68k.cc:359
std::shared_ptr< Linker::Segment > stack_segment
Segment to collect stack (Concurrent DOS 68K only)
Definition cpm68k.h:344
void Clear() override
Resets all fields to their default values, deallocate memory.
Definition cpm68k.cc:82
void SetOptions(std::map< std::string, std::string > &options) override
Passes command line parameters as settings over to format object.
Definition cpm68k.cc:693
std::shared_ptr< Linker::Contents > code
Storage for code segment.
Definition cpm68k.h:204
system_type system
The system which will load the executable.
Definition cpm68k.h:292
void ReadFile(const std::shared_ptr< Linker::Reader > &rd) override
Loads file into memory.
Definition cpm68k.cc:93
std::vector< Linker::OptionDescription< void > * > GetLinkerScriptParameterNames() override
Returns a list of the parameters used in the linker scripts, used for documentation.
Definition cpm68k.cc:683
std::shared_ptr< Linker::Segment > DataSegment()
Return data segment (if it exists)
Definition cpm68k.cc:650
offset_t ImageSize() const override
Retrieves the offset of the byte after the last one belonging to this format from the first one.
Definition cpm68k.cc:354
void CalculateValues() override
Intermediate step between processing module and generating output file to set up headers and manageme...
Definition cpm68k.cc:607
system_type
Different systems have different relocation formats and expectations as to what segments should be pr...
Definition cpm68k.h:262
@ SYSTEM_GEMDOS
Digital Research GEMDOS, Atari TOS, only contiguous, text load address field replaced by program fiel...
Definition cpm68k.h:278
@ SYSTEM_UNKNOWN
Unknown system: use GEMDOS with no relocations.
Definition cpm68k.h:266
@ SYSTEM_CDOS68K
Digital Research Concurrent DOS 68K, non-contiguous not allowed, but relocations can be in CP/M-68K f...
Definition cpm68k.h:286
@ SYSTEM_GEMDOS_EARLY
Digital Research GEMDOS, only contiguous, relocations always present, header is an unusual 0x1E bytes...
Definition cpm68k.h:274
@ SYSTEM_HUMAN68K
Sharp Corporation & Hudson Soft Human68k .z executable, only contiguous, no relocations or symbol tab...
Definition cpm68k.h:282
@ SYSTEM_CPM68K
Digital Research CP/M-68K, uses CP/M-68K relocations.
Definition cpm68k.h:270
uint32_t code_size
Size of the code/text segment.
Definition cpm68k.h:157
char signature[2]
The magic number at the beginning of the executable file, one of 0x601A (contiguous),...
Definition cpm68k.h:152
void ProcessModule(Linker::Module &module) override
Processes the module object and initializes format fields.
Definition cpm68k.cc:931
void Dump(Dumper::Dumper &dump) const override
Display file contents in a nice manner.
Definition cpm68k.cc:467
uint32_t symbol_table_size
Size of the symbol table.
Definition cpm68k.h:169
uint32_t data_size
Size of the initialized data segment.
Definition cpm68k.h:161
uint32_t data_address
Load address of the initialized data segment. Only relevant for non-contiguous executables (CP/M-68K)...
Definition cpm68k.h:191
An abstract interface that separates structure and presentation of the data inside a file.
Definition dumper.h:1009
offset_t WriteFile(const std::shared_ptr< Writer > &wr) const override=0
Stores data in memory to file.
Encodes an object module file as a collection of sections, symbols and relocations.
Definition module.h:24
Helper class that contains the options interpreted by the format.
Definition options.h:499
Documents and handles command line options.
Definition options.h:306
virtual std::string GetDefaultExtension(Module &module, std::string filename) const
Appends a default extension to the filename.
A helper class to collect sections into segments.
Definition segment_manager.h:32
unsigned segment
Segment value, as required by CP/M-68K, they take the value that is stored in file: 1 for data,...
Definition cpm68k.h:220
size_t size
Size of value to relocate.
Definition cpm68k.h:216