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::Contents> code = nullptr;
109 std::shared_ptr<Linker::Contents> 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 struct Symbol
132 {
133 std::string name;
134 enum symbol_type
135 {
136 LIBRARY_START = 0x0040,
137 OBJECT_START = 0x0080,
138 BSS_BASED = 0x0100,
139 TEXT_BASED = 0x0200,
140 DATA_BASED = 0x0400,
141 EXTERNAL = 0x0800,
142 REGISTER = 0x1000,
143 GLOBAL = 0x2000,
144 EQUATED = 0x4000,
145 DEFINED = 0x8000,
146 };
147 uint16_t type;
148 uint32_t value;
149
150 static Symbol ReadFile(Linker::Reader& rd);
151 void WriteFile(Linker::Writer& wr) const;
152 };
153 std::vector<Symbol> symbols;
154
155 magic_type GetSignature() const;
156
157 void SetSignature(magic_type magic);
158
189
194
195 void Clear() override;
196
198 : system(system)
199 {
200 }
201
203 : system(system)
204 {
205 SetSignature(magic);
206 }
207
208 void ReadFile(Linker::Reader& rd) override;
209
210 template <typename SizeType>
211 static offset_t CDOS68K_MeasureRelocations(std::map<uint32_t, SizeType> relocations)
212 {
213 /* TODO: test */
214 offset_t count = 0;
215 offset_t last_relocation = 0;
216 for(auto it : relocations)
217 {
218 offset_t difference = it.first - last_relocation;
219 if(difference != 0 && difference <= 0x7C)
220 {
221 count += 1;
222 }
223 else if(difference < 0x100)
224 {
225 count += 2;
226 }
227 else if(difference < 0x10000)
228 {
229 count += 3;
230 }
231 else
232 {
233 count += 5;
234 }
235 }
236 return count;
237 }
238
239 template <typename SizeType>
240 static void CDOS68K_WriteRelocations(Linker::Writer& wr, std::map<uint32_t, SizeType> relocations)
241 {
242 /* TODO: test */
243 offset_t last_relocation = 0;
244 for(auto it : relocations)
245 {
246 offset_t difference = it.first - last_relocation;
247 uint8_t highbit = it.second/*.size*/ == 2 ? 0x80 : 0x00;
248 if(difference != 0 && difference <= 0x7C)
249 {
250 wr.WriteWord(1, highbit | difference);
251 }
252 else if(difference < 0x100)
253 {
254 wr.WriteWord(1, highbit | 0x7D);
255 wr.WriteWord(1, difference);
256 }
257 else if(difference < 0x10000)
258 {
259 wr.WriteWord(1, highbit | 0x7E);
260 wr.WriteWord(2, difference);
261 }
262 else
263 {
264 wr.WriteWord(1, highbit | 0x7F);
265 wr.WriteWord(4, difference);
266 }
267 last_relocation = it.first;
268 }
269 wr.WriteWord(1, 0);
270 }
271
272 template <typename SizeType, typename Format>
273 static void CDOS68K_ReadRelocations(Linker::Reader& rd, std::map<uint32_t, SizeType> relocations, const Format& format)
274 {
275 /* TODO: test */
276 offset_t offset = 0;
277 while(true)
278 {
279 uint8_t byte = rd.ReadUnsigned(1);
280 size_t size = (byte & 0x80) ? 2 : 4;
281 byte &= 0x7F;
282 if(byte == 0)
283 {
284 break;
285 }
286 else if(byte <= 0x7C)
287 {
288 offset += byte;
289 }
290 else if(byte == 0x7D)
291 {
292 offset += rd.ReadUnsigned(1);
293 }
294 else if(byte == 0x7E)
295 {
296 offset += rd.ReadUnsigned(2);
297 }
298 else /*if(byte == 0x7F)*/
299 {
300 offset += rd.ReadUnsigned(4);
301 }
302 relocations[offset] = SizeType::Create(size, offset, format);
303 }
304 }
305
306 offset_t MeasureRelocations() const;
307
308 offset_t ImageSize() const override;
309
311 offset_t WriteFile(Linker::Writer& wr) const override;
312
313 void Dump(Dumper::Dumper& dump) const override;
314
315 void CalculateValues() override;
316
317 /* * * Writer members * * */
318
320 {
321 public:
322 Linker::Option<bool> noreloc{"noreloc", "Suppress generating relocations"};
323 Linker::Option<bool> reloc{"reloc", "Force relocation generation"};
324 // TODO: make stack size a parameter (for Concurrent DOS 68K)
325 // TODO: make parameters for system and format type
326
328 {
329 InitializeFields(noreloc, reloc);
330 }
331 };
332
337
339 std::shared_ptr<Linker::Segment> bss_segment;
341 std::shared_ptr<Linker::Segment> stack_segment;
342
344 std::shared_ptr<Linker::Segment> CodeSegment();
345 std::shared_ptr<const Linker::Segment> CodeSegment() const;
346
348 std::shared_ptr<Linker::Segment> DataSegment();
349 std::shared_ptr<const Linker::Segment> DataSegment() const;
350
351 unsigned FormatAdditionalSectionFlags(std::string section_name) const override;
352
353 static std::vector<Linker::OptionDescription<void> *> ParameterNames;
354 std::vector<Linker::OptionDescription<void> *> GetLinkerScriptParameterNames() override;
355
356 std::shared_ptr<Linker::OptionCollector> GetOptions() override;
357
358 void SetOptions(std::map<std::string, std::string>& options) override;
359
360 void OnNewSegment(std::shared_ptr<Linker::Segment> segment) override;
361
362 void CreateDefaultSegments();
363
364 std::unique_ptr<Script::List> GetScript(Linker::Module& module);
365
366 void Link(Linker::Module& module);
367
368 void ProcessModule(Linker::Module& module) override;
369
370 void GenerateFile(std::string filename, Linker::Module& module) override;
371
373 std::string GetDefaultExtension(Linker::Module& module, std::string filename) const override;
374 };
375
376}
377
378#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:1028
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:764
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:688
std::shared_ptr< Linker::Segment > bss_segment
Segment to collect bss.
Definition cpm68k.h:339
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: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:83
offset_t WriteFile(Linker::Writer &wr) const override
Stores data in memory to file.
Definition cpm68k.cc:359
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:336
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
std::shared_ptr< Linker::Contents > data
Storage for data segment.
Definition cpm68k.h:109
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:341
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:105
system_type system
The system which will load the executable.
Definition cpm68k.h:193
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 size of stored data.
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:163
@ SYSTEM_GEMDOS
Digital Research GEMDOS, Atari TOS, only contiguous, text load address field replaced by program fiel...
Definition cpm68k.h:179
@ SYSTEM_UNKNOWN
Unknown system: use GEMDOS with no relocations.
Definition cpm68k.h:167
@ SYSTEM_CDOS68K
Digital Research Concurrent DOS 68K, non-contiguous not allowed, but relocations can be in CP/M-68K f...
Definition cpm68k.h:187
@ SYSTEM_GEMDOS_EARLY
Digital Research GEMDOS, only contiguous, relocations always present, header is an unusual 0x1E bytes...
Definition cpm68k.h:175
@ SYSTEM_HUMAN68K
Sharp Corporation & Hudson Soft Human68k .z executable, only contiguous, no relocations or symbol tab...
Definition cpm68k.h:183
@ SYSTEM_CPM68K
Digital Research CP/M-68K, uses CP/M-68K relocations.
Definition cpm68k.h:171
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:931
void Dump(Dumper::Dumper &dump) const override
Display file contents in a nice manner.
Definition cpm68k.cc:467
void ReadFile(Linker::Reader &rd) override
Loads file into memory.
Definition cpm68k.cc:93
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:773
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:474
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, encapsulating functionality needed to import binary data.
Definition reader.h:20
uint64_t ReadUnsigned(size_t bytes, EndianType endiantype)
Read an unsigned word.
Definition reader.cc:157
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