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{
28 class CPM68KFormat : public virtual Linker::SegmentManager
29 {
30 public:
31 /* * * General members * * */
32
37 {
49 MAGIC_CRUNCHED, /* Concurrent DOS 68K only */
50 };
51
53 char signature[2] = { 0x60, 0x1A };
54
58 uint32_t code_size = 0;
62 uint32_t data_size = 0;
66 uint32_t bss_size = 0;
70 uint32_t symbol_table_size = 0;
74 uint32_t stack_size = 0;
75
79 uint32_t code_address = 0;
83 uint32_t program_flags = 0; /* TODO: make parameter */
84
92 uint32_t data_address = 0;
96 uint32_t bss_address = 0;
100 offset_t file_size = 0;
101
105 std::shared_ptr<Linker::Image> code = nullptr;
109 std::shared_ptr<Linker::Image> data = nullptr;
110
111 /* filled in automatically */
113 {
117 size_t size;
121 unsigned segment;
122 operator size_t() const;
123
124 static Relocation Create(size_t size, uint32_t offset, const CPM68KFormat& format);
125 };
129 std::map<uint32_t, Relocation> relocations;
130
131 magic_type GetSignature() const;
132
133 void SetSignature(magic_type magic);
134
165
170
171 void Clear() override;
172
174 : system(system)
175 {
176 }
177
179 : system(system)
180 {
181 SetSignature(magic);
182 }
183
184 void ReadFile(Linker::Reader& rd) override;
185
186 template <typename SizeType>
187 static offset_t CDOS68K_MeasureRelocations(std::map<uint32_t, SizeType> relocations)
188 {
189 /* TODO: test */
190 offset_t count = 0;
191 offset_t last_relocation = 0;
192 for(auto it : relocations)
193 {
194 offset_t difference = it.first - last_relocation;
195 if(difference != 0 && difference <= 0x7C)
196 {
197 count += 1;
198 }
199 else if(difference < 0x100)
200 {
201 count += 2;
202 }
203 else if(difference < 0x10000)
204 {
205 count += 3;
206 }
207 else
208 {
209 count += 5;
210 }
211 }
212 return count;
213 }
214
215 template <typename SizeType>
216 static void CDOS68K_WriteRelocations(Linker::Writer& wr, std::map<uint32_t, SizeType> relocations)
217 {
218 /* TODO: test */
219 offset_t last_relocation = 0;
220 for(auto it : relocations)
221 {
222 offset_t difference = it.first - last_relocation;
223 uint8_t highbit = it.second/*.size*/ == 2 ? 0x80 : 0x00;
224 if(difference != 0 && difference <= 0x7C)
225 {
226 wr.WriteWord(1, highbit | difference);
227 }
228 else if(difference < 0x100)
229 {
230 wr.WriteWord(1, highbit | 0x7D);
231 wr.WriteWord(1, difference);
232 }
233 else if(difference < 0x10000)
234 {
235 wr.WriteWord(1, highbit | 0x7E);
236 wr.WriteWord(2, difference);
237 }
238 else
239 {
240 wr.WriteWord(1, highbit | 0x7F);
241 wr.WriteWord(4, difference);
242 }
243 last_relocation = it.first;
244 }
245 wr.WriteWord(1, 0);
246 }
247
248 template <typename SizeType, typename Format>
249 static void CDOS68K_ReadRelocations(Linker::Reader& rd, std::map<uint32_t, SizeType> relocations, const Format& format)
250 {
251 /* TODO: test */
252 offset_t offset = 0;
253 while(true)
254 {
255 uint8_t byte = rd.ReadUnsigned(1);
256 size_t size = (byte & 0x80) ? 2 : 4;
257 byte &= 0x7F;
258 if(byte == 0)
259 {
260 break;
261 }
262 else if(byte <= 0x7C)
263 {
264 offset += byte;
265 }
266 else if(byte == 0x7D)
267 {
268 offset += rd.ReadUnsigned(1);
269 }
270 else if(byte == 0x7E)
271 {
272 offset += rd.ReadUnsigned(2);
273 }
274 else /*if(byte == 0x7F)*/
275 {
276 offset += rd.ReadUnsigned(4);
277 }
278 relocations[offset] = SizeType::Create(size, offset, format);
279 }
280 }
281
282 offset_t MeasureRelocations() const;
283
284 offset_t ImageSize() const override;
285
287 offset_t WriteFile(Linker::Writer& wr) const override;
288
289 void Dump(Dumper::Dumper& dump) const override;
290
291 void CalculateValues() override;
292
293 /* * * Writer members * * */
294
296 {
297 public:
298 Linker::Option<bool> noreloc{"noreloc", "Suppress generating relocations"};
299 Linker::Option<bool> reloc{"reloc", "Force relocation generation"};
300
302 {
303 InitializeFields(noreloc, reloc);
304 }
305 };
306
311
313 std::shared_ptr<Linker::Segment> bss_segment;
315 std::shared_ptr<Linker::Segment> stack_segment;
316
318 std::shared_ptr<Linker::Segment> CodeSegment();
319 std::shared_ptr<const Linker::Segment> CodeSegment() const;
320
322 std::shared_ptr<Linker::Segment> DataSegment();
323 std::shared_ptr<const Linker::Segment> DataSegment() const;
324
325 unsigned FormatAdditionalSectionFlags(std::string section_name) const override;
326
327 static std::vector<Linker::OptionDescription<void> *> ParameterNames;
328 std::vector<Linker::OptionDescription<void> *> GetLinkerScriptParameterNames() override;
329
330 std::shared_ptr<Linker::OptionCollector> GetOptions() override;
331
332 void SetOptions(std::map<std::string, std::string>& options) override;
333
334 void OnNewSegment(std::shared_ptr<Linker::Segment> segment) override;
335
336 void CreateDefaultSegments();
337
338 std::unique_ptr<Script::List> GetScript(Linker::Module& module);
339
340 void Link(Linker::Module& module);
341
342 void ProcessModule(Linker::Module& module) override;
343
344 void GenerateFile(std::string filename, Linker::Module& module) override;
345
347 std::string GetDefaultExtension(Linker::Module& module, std::string filename) const override;
348 };
349
350}
351
352#endif /* CPM68K_H */
The native executable format for the Motorola 68000 port of CP/M.
Definition cpm68k.h:29
void GenerateFile(std::string filename, Linker::Module &module) override
The main function that handles processing, calculating and generating the final image.
Definition cpm68k.cc:969
offset_t file_size
Size of entire file, not used for generation.
Definition cpm68k.h:100
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:705
uint32_t stack_size
Size of the stack segment. Only used by Concurrent DOS 68K.
Definition cpm68k.h:74
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:79
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:629
std::shared_ptr< Linker::Segment > bss_segment
Segment to collect bss.
Definition cpm68k.h:313
uint32_t bss_size
Size of the uninitialized data (bss) segment. Human68k includes the stack in it.
Definition cpm68k.h:66
std::string GetDefaultExtension(Linker::Module &module, std::string filename) const override
Appends a default extension to the filename.
Definition cpm68k.cc:991
std::shared_ptr< Linker::Segment > CodeSegment()
Return code segment (if it exists)
Definition cpm68k.cc:581
uint32_t program_flags
Program flags, used by GEMDOS.
Definition cpm68k.h:83
offset_t WriteFile(Linker::Writer &wr) const override
Stores data in memory to file.
Definition cpm68k.cc:337
uint32_t bss_address
Load address of the uninitialized data (bss) segment. Only relevant for non-contiguous executables (C...
Definition cpm68k.h:96
std::map< uint32_t, Relocation > relocations
Relocations, not used for Human68k.
Definition cpm68k.h:129
bool option_no_relocation
Makes sure no relocations are placed into the output file.
Definition cpm68k.h:310
std::shared_ptr< Linker::Image > data
Storage for data segment.
Definition cpm68k.h:109
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:88
magic_type
Represents the magic number at the beginning of the executable file.
Definition cpm68k.h:37
@ MAGIC_CONTIGUOUS
Contiguous executables (magic value 0x601A in big endian) must load the code, data,...
Definition cpm68k.h:41
@ MAGIC_CRUNCHED
Contiguous executables with crunched relocations (magic value 0x601C in big endian),...
Definition cpm68k.h:49
@ MAGIC_NONCONTIGUOUS
Non-contiguous executables (magic value 0x601B in big endian) can load the code, data,...
Definition cpm68k.h:45
std::shared_ptr< Linker::Segment > stack_segment
Segment to collect stack (Concurrent DOS 68K only)
Definition cpm68k.h:315
void Clear() override
Resets all fields to their default values, deallocate memory.
Definition cpm68k.cc:66
void SetOptions(std::map< std::string, std::string > &options) override
Passes command line parameters as settings over to format object.
Definition cpm68k.cc:634
system_type system
The system which will load the executable.
Definition cpm68k.h:169
std::vector< Linker::OptionDescription< void > * > GetLinkerScriptParameterNames() override
Returns a list of the parameters used in the linker scripts, used for documentation.
Definition cpm68k.cc:624
std::shared_ptr< Linker::Segment > DataSegment()
Return data segment (if it exists)
Definition cpm68k.cc:591
offset_t ImageSize() const override
Retrieves size of stored data.
Definition cpm68k.cc:332
void CalculateValues() override
Intermediate step between processing module and generating output file to set up headers and manageme...
Definition cpm68k.cc:548
system_type
Different systems have different relocation formats and expectations as to what segments should be pr...
Definition cpm68k.h:139
@ SYSTEM_GEMDOS
Digital Research GEMDOS, Atari TOS, only contiguous, text load address field replaced by program fiel...
Definition cpm68k.h:155
@ SYSTEM_UNKNOWN
Unknown system: use GEMDOS with no relocations.
Definition cpm68k.h:143
@ SYSTEM_CDOS68K
Digital Research Concurrent DOS 68K, non-contiguous not allowed, but relocations can be in CP/M-68K f...
Definition cpm68k.h:163
@ SYSTEM_GEMDOS_EARLY
Digital Research GEMDOS, only contiguous, relocations always present, header is an unusual 0x1E bytes...
Definition cpm68k.h:151
@ SYSTEM_HUMAN68K
Sharp Corporation & Hudson Soft Human68k .z executable, only contiguous, no relocations or symbol tab...
Definition cpm68k.h:159
@ SYSTEM_CPM68K
Digital Research CP/M-68K, uses CP/M-68K relocations.
Definition cpm68k.h:147
uint32_t code_size
Size of the code/text segment.
Definition cpm68k.h:58
char signature[2]
The magic number at the beginning of the executable file, one of 0x601A (contiguous),...
Definition cpm68k.h:53
void ProcessModule(Linker::Module &module) override
Processes the module object and initializes format fields.
Definition cpm68k.cc:872
void Dump(Dumper::Dumper &dump) const override
Display file contents in a nice manner.
Definition cpm68k.cc:441
void ReadFile(Linker::Reader &rd) override
Loads file into memory.
Definition cpm68k.cc:77
std::shared_ptr< Linker::Image > code
Storage for code segment.
Definition cpm68k.h:105
uint32_t symbol_table_size
Size of the symbol table.
Definition cpm68k.h:70
uint32_t data_size
Size of the initialized data segment.
Definition cpm68k.h:62
uint32_t data_address
Load address of the initialized data segment. Only relevant for non-contiguous executables (CP/M-68K)...
Definition cpm68k.h:92
An abstract interface that separates structure and presentation of the data inside a file.
Definition dumper.h:586
offset_t WriteFile(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:467
Documents and handles command line options.
Definition options.h:303
virtual std::string GetDefaultExtension(Module &module, std::string filename) const
Appends a default extension to the filename.
A helper class, encapsulating functionality needed to import binary data.
Definition reader.h:16
uint64_t ReadUnsigned(size_t bytes, EndianType endiantype)
Read an unsigned word.
Definition reader.cc:86
A helper class to collect sections into segments.
Definition segment_manager.h:32
A helper class, encapsulating functionality needed to export binary data.
Definition writer.h:15
void WriteWord(size_t bytes, uint64_t value, EndianType endiantype)
Read a word.
Definition writer.cc:67
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:121
size_t size
Size of value to relocate.
Definition cpm68k.h:117