1 /*
2 Z88DK Z80 Module Assembler
3
4 Copyright (C) Paulo Custodio, 2011-2020
5 License: The Artistic License 2.0, http://www.perlfoundation.org/artistic_license_2_0
6 Repository: https://github.com/z88dk/z88dk
7
8 Manage the code area in memory
9 */
10
11 #include "codearea.h"
12 #include "die.h"
13 #include "errors.h"
14 #include "fileutil.h"
15 #include "init.h"
16 #include "listfile.h"
17 #include "options.h"
18 #include "strutil.h"
19 #include "utstring.h"
20 #include "z80asm.h"
21 #include <memory.h>
22
23 /*-----------------------------------------------------------------------------
24 * global data
25 *----------------------------------------------------------------------------*/
26 static SectionHash *g_sections;
27 static Section *g_cur_section;
28 static Section *g_default_section;
29 static Section *g_last_section;
30 static int g_cur_module;
31
32 /*-----------------------------------------------------------------------------
33 * Initialize and Terminate module
34 *----------------------------------------------------------------------------*/
DEFINE_init_module()35 DEFINE_init_module()
36 {
37 reset_codearea(); /* init default section */
38 }
39
DEFINE_dtor_module()40 DEFINE_dtor_module()
41 {
42 OBJ_DELETE( g_sections );
43 g_cur_section = g_default_section = g_last_section = NULL;
44 }
45
46 /*-----------------------------------------------------------------------------
47 * Named Section of code, introduced by "SECTION" keyword
48 *----------------------------------------------------------------------------*/
49 DEF_CLASS( Section );
50 DEF_CLASS_HASH( Section, false );
51
Section_init(Section * self)52 void Section_init (Section *self)
53 {
54 self->name = ""; /* default: empty section */
55 self->addr = 0;
56 self->origin = -1;
57 self->align = 1;
58 self->origin_found = false;
59 self->origin_opts = false;
60 self->section_split = false;
61 self->asmpc = 0;
62 self->asmpc_phase = -1;
63 self->opcode_size = 0;
64
65 self->bytes = OBJ_NEW(ByteArray);
66 OBJ_AUTODELETE(self->bytes) = false;
67
68 self->reloc = OBJ_NEW(intArray);
69 OBJ_AUTODELETE(self->reloc) = false;
70
71 self->module_start = OBJ_NEW(intArray);
72 OBJ_AUTODELETE( self->module_start ) = false;
73 }
74
Section_copy(Section * self,Section * other)75 void Section_copy (Section *self, Section *other)
76 {
77 self->bytes = ByteArray_clone(other->bytes);
78 self->reloc = intArray_clone(other->reloc);
79 self->module_start = intArray_clone(other->module_start);
80 }
81
Section_fini(Section * self)82 void Section_fini (Section *self)
83 {
84 OBJ_DELETE(self->bytes);
85 OBJ_DELETE(self->reloc);
86 OBJ_DELETE(self->module_start);
87 }
88
89 /*-----------------------------------------------------------------------------
90 * Handle list of current sections
91 *----------------------------------------------------------------------------*/
92
93 /*-----------------------------------------------------------------------------
94 * init to default section ""; only called at startup
95 *----------------------------------------------------------------------------*/
reset_codearea(void)96 void reset_codearea( void )
97 {
98 init_module();
99 SectionHash_remove_all( g_sections );
100 g_cur_section = g_default_section = g_last_section = NULL;
101 new_section("");
102 }
103
104 /*-----------------------------------------------------------------------------
105 * return size of current section
106 *----------------------------------------------------------------------------*/
get_section_size(Section * section)107 int get_section_size( Section *section )
108 {
109 init_module();
110 return ByteArray_size( section->bytes );
111 }
112
113 /*-----------------------------------------------------------------------------
114 * compute total size of all sections
115 *----------------------------------------------------------------------------*/
get_sections_size(void)116 int get_sections_size( void )
117 {
118 Section *section;
119 SectionHashElem *iter;
120 int size;
121
122 size = 0;
123 for ( section = get_first_section( &iter ) ; section != NULL ;
124 section = get_next_section( &iter ) )
125 {
126 size += get_section_size( section );
127 }
128 return size;
129 }
130
131 /*-----------------------------------------------------------------------------
132 * get section by name, creates a new section if new name;
133 * make it the current section
134 *----------------------------------------------------------------------------*/
new_section(const char * name)135 Section *new_section( const char *name )
136 {
137 int last_id;
138
139 init_module();
140 g_cur_section = SectionHash_get( g_sections, name );
141 if ( g_cur_section == NULL )
142 {
143 g_cur_section = OBJ_NEW( Section );
144 g_cur_section->name = spool_add( name );
145 SectionHash_set( & g_sections, name, g_cur_section );
146
147 /* set first and last sections */
148 if ( g_default_section == NULL )
149 g_default_section = g_cur_section;
150 g_last_section = g_cur_section;
151
152 /* define start address of all existing modules = 0, except for default section */
153 if ( g_default_section != NULL && *name != '\0' )
154 {
155 last_id = intArray_size( g_default_section->module_start ) - 1;
156 if ( last_id >= 0 )
157 intArray_item( g_cur_section->module_start, last_id ); /* init [0..module_id] to zero */
158 }
159 }
160 return g_cur_section;
161 }
162
163 /*-----------------------------------------------------------------------------
164 * get/set current section
165 *----------------------------------------------------------------------------*/
get_cur_section(void)166 Section *get_cur_section( void )
167 {
168 init_module();
169 return g_cur_section;
170 }
171
set_cur_section(Section * section)172 Section *set_cur_section( Section *section )
173 {
174 init_module();
175 return (g_cur_section = section); /* assign and return */
176 }
177
178 /*-----------------------------------------------------------------------------
179 * iterate through sections
180 * pointer to iterator may be NULL if no need to iterate
181 *----------------------------------------------------------------------------*/
get_first_section(SectionHashElem ** piter)182 Section *get_first_section( SectionHashElem **piter )
183 {
184 SectionHashElem *iter;
185
186 init_module();
187 if ( piter == NULL )
188 piter = &iter; /* user does not need to iterate */
189
190 *piter = SectionHash_first( g_sections );
191 return (*piter == NULL) ? NULL : (Section *) (*piter)->value;
192 }
193
get_last_section(void)194 Section *get_last_section( void )
195 {
196 init_module();
197 return g_last_section;
198 }
199
get_next_section(SectionHashElem ** piter)200 Section *get_next_section( SectionHashElem **piter )
201 {
202 init_module();
203 *piter = SectionHash_next( *piter );
204 return (*piter == NULL) ? NULL : (Section *) (*piter)->value;
205 }
206
207 /*-----------------------------------------------------------------------------
208 * Handle current module
209 *----------------------------------------------------------------------------*/
get_last_module_id(void)210 static int get_last_module_id( void )
211 {
212 init_module();
213 return intArray_size( g_default_section->module_start ) - 1;
214 }
215
get_cur_module_id(void)216 int get_cur_module_id( void )
217 {
218 init_module();
219 return g_cur_module;
220 }
221
set_cur_module_id(int module_id)222 void set_cur_module_id( int module_id )
223 {
224 init_module();
225 xassert( module_id >= 0 );
226 xassert( module_id <= get_last_module_id() );
227 g_cur_module = module_id;
228 }
229
230 /*-----------------------------------------------------------------------------
231 * return start and end offset for given section and module ID
232 *----------------------------------------------------------------------------*/
section_module_start(Section * section,int module_id)233 static int section_module_start( Section *section, int module_id )
234 {
235 int addr, *item;
236 int i;
237 int cur_size;
238
239 init_module();
240 cur_size = intArray_size( section->module_start );
241 if ( cur_size > module_id )
242 addr = *( intArray_item( section->module_start, module_id ) );
243 else
244 {
245 addr = 0;
246 for ( i = cur_size < 1 ? 0 : cur_size - 1;
247 i < module_id; i++ )
248 {
249 item = intArray_item( section->module_start, i );
250 if ( *item < addr )
251 *item = addr;
252 else
253 addr = *item;
254 }
255
256 /* update address with current code index */
257 item = intArray_item( section->module_start, module_id );
258 xassert( get_section_size( section ) >= addr );
259
260 addr = *item = get_section_size( section );
261 }
262 return addr;
263 }
264
section_module_size(Section * section,int module_id)265 static int section_module_size( Section *section, int module_id )
266 {
267 int last_module_id = get_last_module_id();
268 int addr, size;
269
270 addr = section_module_start( section, module_id );
271 if ( module_id < last_module_id )
272 size = section_module_start( section, module_id + 1 ) - addr;
273 else
274 size = get_section_size( section ) - addr;
275
276 return size;
277 }
278
get_cur_module_start(void)279 int get_cur_module_start( void ) { return section_module_start( g_cur_section, g_cur_module ); }
get_cur_module_size(void)280 int get_cur_module_size( void ) { return section_module_size( g_cur_section, g_cur_module ); }
281
282 /*-----------------------------------------------------------------------------
283 * allocate the addr of each of the sections, concatenating the sections in
284 * consecutive addresses, or starting from a new address if a section
285 * has a defined origin. Start at the command line origin, or at 0 if negative
286 *----------------------------------------------------------------------------*/
sections_alloc_addr(void)287 void sections_alloc_addr(void)
288 {
289 Section *section, *next_section;
290 SectionHashElem *iter;
291 int addr;
292
293 init_module();
294
295 /* allocate addr in sequence */
296 addr = 0;
297 for (section = get_first_section(&iter); section != NULL; section = next_section) {
298 if (section->origin >= 0) /* break in address space */
299 addr = section->origin;
300
301 section->addr = addr;
302 addr += get_section_size(section);
303
304 // check ALIGN of next section, extend this section if needed
305 next_section = get_next_section(&iter);
306 if (next_section != NULL && !(next_section->origin >= 0) && next_section->align > 1
307 && get_section_size(next_section) > 0) {
308 int above = addr % next_section->align;
309 if (above > 0) {
310 for (int i = next_section->align - above; i > 0; i--) {
311 *(ByteArray_push(section->bytes)) = opts.filler;
312 addr++;
313 }
314 }
315 }
316 }
317 }
318
319 /*-----------------------------------------------------------------------------
320 * allocate a new module, setup module_start[] and reset ASMPC of all sections,
321 * return new unique ID; make it the current module
322 *----------------------------------------------------------------------------*/
new_module_id(void)323 int new_module_id( void )
324 {
325 Section *section;
326 SectionHashElem *iter;
327 int module_id;
328
329 init_module();
330 module_id = get_last_module_id() + 1;
331
332 /* expand all sections this new ID */
333 for ( section = get_first_section( &iter ) ; section != NULL ;
334 section = get_next_section( &iter ) )
335 {
336 section->asmpc = 0;
337 section->asmpc_phase = -1;
338 section->opcode_size = 0;
339 (void) section_module_start( section, module_id );
340 }
341
342 /* init to default section */
343 set_cur_section( g_default_section );
344
345 return (g_cur_module = module_id); /* assign and return */
346 }
347
348 /*-----------------------------------------------------------------------------
349 * Handle ASMPC
350 * set_PC() defines the instruction start address
351 * every byte added increments an offset but keeps ASMPC with start of opcode
352 * next_PC() moves to the next opcode
353 *----------------------------------------------------------------------------*/
set_PC(int addr)354 void set_PC( int addr )
355 {
356 init_module();
357 g_cur_section->asmpc = addr;
358 g_cur_section->opcode_size = 0;
359 }
360
next_PC(void)361 int next_PC( void )
362 {
363 init_module();
364 g_cur_section->asmpc += g_cur_section->opcode_size;
365 if (g_cur_section->asmpc_phase >= 0)
366 g_cur_section->asmpc_phase += g_cur_section->opcode_size;
367
368 g_cur_section->opcode_size = 0;
369 return g_cur_section->asmpc;
370 }
371
get_PC(void)372 int get_PC(void)
373 {
374 init_module();
375 return g_cur_section->asmpc;
376 }
377
get_phased_PC(void)378 int get_phased_PC(void)
379 {
380 init_module();
381 return g_cur_section->asmpc_phase;
382 }
383
inc_PC(int num_bytes)384 static void inc_PC( int num_bytes )
385 {
386 init_module();
387 g_cur_section->opcode_size += num_bytes;
388 }
389
390 /*-----------------------------------------------------------------------------
391 * Check space before allocating bytes in section
392 *----------------------------------------------------------------------------*/
check_space(int addr,int num_bytes)393 static void check_space( int addr, int num_bytes )
394 {
395 init_module();
396 if (addr + num_bytes > MAXCODESIZE && !g_cur_section->max_codesize_issued)
397 {
398 error_max_codesize((long)MAXCODESIZE);
399 g_cur_section->max_codesize_issued = true;
400 }
401 }
402
403 /* reserve space in bytes, increment PC if buffer expanded
404 assert only the last module can be expanded */
alloc_space(int addr,int num_bytes)405 static byte_t *alloc_space( int addr, int num_bytes )
406 {
407 int base_addr;
408 int old_size, new_size;
409 byte_t *buffer;
410
411 init_module();
412 base_addr = get_cur_module_start();
413 old_size = get_cur_module_size();
414
415 /* cannot expand unless last module */
416 if ( get_cur_module_id() != get_last_module_id() )
417 xassert( addr + num_bytes <= old_size );
418
419 check_space( base_addr + addr, num_bytes );
420
421 /* reserve space */
422 if ( num_bytes > 0 )
423 {
424 (void) ByteArray_item( g_cur_section->bytes, base_addr + addr + num_bytes - 1 );
425 buffer = ByteArray_item( g_cur_section->bytes, base_addr + addr );
426 }
427 else
428 buffer = NULL; /* no allocation */
429
430 /* advance PC if past end of previous buffer */
431 new_size = get_cur_module_size();
432 if ( new_size > old_size )
433 inc_PC( new_size - old_size );
434
435 return buffer;
436 }
437
438 /*-----------------------------------------------------------------------------
439 * patch a value at a position, or append to the end of the code area
440 * the patch address is relative to current module and current section
441 * and is incremented after store
442 *----------------------------------------------------------------------------*/
patch_value(int addr,int value,int num_bytes)443 void patch_value( int addr, int value, int num_bytes )
444 {
445 byte_t *buffer;
446
447 init_module();
448 buffer = alloc_space( addr, num_bytes );
449 while ( num_bytes-- > 0 )
450 {
451 *buffer++ = value & 0xFF;
452 value >>= 8;
453 }
454 }
455
append_value(int value,int num_bytes)456 void append_value( int value, int num_bytes )
457 {
458 init_module();
459 patch_value(get_cur_module_size(), value, num_bytes);
460
461 if ( opts.list )
462 list_append( value, num_bytes );
463 }
464
patch_byte(int addr,byte_t byte1)465 void patch_byte( int addr, byte_t byte1 ) { patch_value( addr, byte1, 1 ); }
patch_word(int addr,int word)466 void patch_word( int addr, int word ) { patch_value( addr, word, 2 ); }
patch_long(int addr,long dword)467 void patch_long( int addr, long dword ) { patch_value( addr, dword, 4 ); }
468
patch_word_be(int addr,int word)469 void patch_word_be(int addr, int word) { patch_value(addr, ((word & 0xFF00) >> 8) | ((word & 0x00FF) << 8), 2); }
470
append_byte(byte_t byte1)471 void append_byte( byte_t byte1 ) { append_value( byte1, 1 ); }
append_word(int word)472 void append_word( int word ) { append_value( word, 2 ); }
append_long(long dword)473 void append_long( long dword ) { append_value( dword, 4 ); }
474
append_word_be(int word)475 void append_word_be(int word) { append_value(((word & 0xFF00) >> 8) | ((word & 0x00FF) << 8), 2); }
476
append_2bytes(byte_t byte1,byte_t byte2)477 void append_2bytes( byte_t byte1, byte_t byte2 )
478 {
479 append_value( byte1, 1 );
480 append_value( byte2, 1 );
481 }
482
append_defs(int num_bytes,byte_t fill)483 void append_defs(int num_bytes, byte_t fill)
484 {
485 while (num_bytes-- > 0)
486 append_byte(fill);
487 }
488
489 /* advance code pointer reserving space, return address of start of buffer */
append_reserve(int num_bytes)490 byte_t *append_reserve( int num_bytes )
491 {
492 init_module();
493 return alloc_space( get_cur_module_size(), num_bytes );
494 }
495
496 /* append binary contents of file, whole file if num_bytes < 0 */
patch_file_contents(FILE * file,int addr,long num_bytes)497 void patch_file_contents( FILE *file, int addr, long num_bytes ) {
498 long start_ptr;
499 byte_t *buffer;
500
501 init_module();
502
503 /* get bin file size */
504 if ( num_bytes < 0 )
505 {
506 start_ptr = ftell( file );
507
508 fseek( file, 0, SEEK_END ); /* file pointer to end of file */
509 num_bytes = ftell( file ) - start_ptr;
510
511 fseek( file, start_ptr, SEEK_SET ); /* file pointer to original position */
512 }
513
514 if ( num_bytes > 0 )
515 {
516 buffer = alloc_space( addr, num_bytes );
517 xfread_bytes(buffer, num_bytes, file);
518 }
519 }
520
patch_from_memory(byte_t * data,int addr,long num_bytes)521 void patch_from_memory(byte_t* data, int addr, long num_bytes) {
522 init_module();
523
524 if (num_bytes > 0) {
525 byte_t *buffer = alloc_space(addr, num_bytes);
526 memcpy(buffer, data, num_bytes);
527 }
528 }
529
append_file_contents(FILE * file,long num_bytes)530 void append_file_contents(FILE *file, long num_bytes)
531 {
532 init_module();
533 patch_file_contents(file, get_cur_module_size(), num_bytes);
534 }
535
536 /*-----------------------------------------------------------------------------
537 * read/write current module to an open file
538 *----------------------------------------------------------------------------*/
fwrite_module_code(FILE * file,int * p_code_size)539 bool fwrite_module_code(FILE *file, int* p_code_size)
540 {
541 Section *section;
542 SectionHashElem *iter;
543 bool wrote_data = false;
544 int code_size = 0;
545 int addr, size;
546
547 init_module();
548 for (section = get_first_section(&iter); section != NULL;
549 section = get_next_section(&iter))
550 {
551 addr = section_module_start(section, g_cur_module);
552 size = section_module_size(section, g_cur_module);
553
554 /* write all sections, even empty ones, to allow user to define sections list by
555 a sequence of SECTION statements
556 exception: empty section, as it is the first one anyway, if no ORG is defined */
557 if (size > 0 || section != get_first_section(NULL) ||
558 section->origin >= 0 || section->align > 1)
559 {
560 xfwrite_dword(size, file);
561 xfwrite_bcount_cstr(section->name, file);
562 write_origin(file, section);
563 xfwrite_dword(section->align, file);
564
565 if (size > 0) /* ByteArray_item(bytes,0) creates item[0]!! */
566 xfwrite_bytes((char *)ByteArray_item(section->bytes, addr), size, file);
567
568 code_size += size;
569 wrote_data = true;
570 }
571 }
572
573 if (wrote_data)
574 xfwrite_dword(-1, file); /* end marker */
575
576 if (p_code_size)
577 *p_code_size = code_size;
578
579 return wrote_data;
580 }
581
582 /*-----------------------------------------------------------------------------
583 * read/write whole code area to an open file
584 *----------------------------------------------------------------------------*/
fwrite_codearea(const char * filename,FILE ** pbinfile,FILE ** prelocfile)585 void fwrite_codearea(const char *filename, FILE **pbinfile, FILE **prelocfile)
586 {
587 STR_DEFINE(new_name, FILENAME_MAX);
588 Section *section;
589 SectionHashElem *iter;
590 int section_size;
591 int cur_section_block_size;
592 int cur_addr;
593
594 init_module();
595
596 cur_addr = -1;
597 cur_section_block_size = 0;
598 for (section = get_first_section(&iter); section != NULL;
599 section = get_next_section(&iter))
600 {
601 section_size = get_section_size(section);
602
603 if (cur_addr < 0)
604 cur_addr = section->addr;
605
606 /* bytes from this section */
607 if (section_size > 0 || section->origin >= 0 || section->section_split)
608 {
609 if (section->name && *section->name) /* only if section name not empty */
610 {
611 /* change current file if address changed, or option -split-bin, or section_split */
612 if ((!opts.relocatable && opts.split_bin) ||
613 section->section_split ||
614 cur_addr != section->addr ||
615 (section != get_first_section(NULL) && section->origin >= 0))
616 {
617 if (opts.appmake)
618 warn_org_ignored(get_obj_filename(filename), section->name);
619 else {
620 Str_set(new_name, path_remove_ext(filename)); /* "test" */
621 Str_append_char(new_name, '_');
622 Str_append(new_name, section->name);
623
624 xfclose_remove_empty(*pbinfile);
625
626 if (opts.verbose)
627 printf("Creating binary '%s'\n", path_canon(get_bin_filename(Str_data(new_name))));
628
629 *pbinfile = xfopen(get_bin_filename(Str_data(new_name)), "wb");
630
631 if (*prelocfile) {
632 xfclose_remove_empty(*prelocfile);
633 *prelocfile = xfopen(get_reloc_filename(Str_data(new_name)), "wb");
634 cur_section_block_size = 0;
635 }
636
637 cur_addr = section->addr;
638 }
639 }
640 }
641
642 xfwrite_bytes((char *)ByteArray_item(section->bytes, 0), section_size, *pbinfile);
643
644 if (*prelocfile) {
645 unsigned i;
646 for (i = 0; i < intArray_size(section->reloc); i++) {
647 xfwrite_word(*(intArray_item(section->reloc, i)) + cur_section_block_size, *prelocfile);
648 }
649 }
650
651 cur_section_block_size += section_size;
652 }
653
654 cur_addr += section_size;
655 }
656
657 STR_DELETE(new_name);
658 }
659
660 /*-----------------------------------------------------------------------------
661 * Assembly directives
662 *----------------------------------------------------------------------------*/
663
664 /* define a new origin, called by the ORG directive
665 * if origin is -1, the section is split creating a new binary file */
set_origin_directive(int origin)666 void set_origin_directive(int origin)
667 {
668 if (CURRENTSECTION->origin_found)
669 error_org_redefined();
670 else
671 {
672 CURRENTSECTION->origin_found = true;
673 if (origin == -1) /* signal split section binary file */
674 CURRENTSECTION->section_split = true;
675 else if (origin >= 0)
676 {
677 if (CURRENTSECTION->origin_opts && CURRENTSECTION->origin >= 0)
678 ; /* ignore ORG, as -r from command line overrides */
679 else
680 CURRENTSECTION->origin = origin;
681 }
682 else
683 error_int_range(origin);
684 }
685 }
686
687 /* define a new origin, called by the --orgin command line option */
set_origin_option(int origin)688 void set_origin_option(int origin)
689 {
690 Section *default_section;
691
692 if (origin < 0 || origin > 0xFFFF)
693 error_int_range((long)origin);
694 else
695 {
696 default_section = get_first_section(NULL);
697 default_section->origin = origin;
698 default_section->origin_opts = true;
699 }
700 }
701
702
read_origin(FILE * file,Section * section)703 void read_origin(FILE* file, Section *section) {
704 int origin = xfread_dword(file);
705 set_origin(origin, section);
706 }
707
set_origin(int origin,Section * section)708 extern void set_origin(int origin, Section *section) {
709 if (origin >= 0) {
710 section->origin = origin;
711 section->section_split = false;
712 }
713 else if (origin == -2) {
714 section->section_split = true;
715 }
716 else {
717 // ignore all other values
718 }
719 }
720
write_origin(FILE * file,Section * section)721 void write_origin(FILE* file, Section *section) {
722 int origin = section->origin;
723 if (origin < 0) {
724 if (section->section_split)
725 origin = -2; /* write -2 for section split */
726 else
727 origin = -1; /* write -1 for not defined */
728 }
729
730 xfwrite_dword(origin, file);
731 }
732
set_phase_directive(int address)733 void set_phase_directive(int address)
734 {
735 if (address >= 0 && address <= 0xFFFF)
736 CURRENTSECTION->asmpc_phase = address;
737 else
738 error_int_range(address);
739 }
740
clear_phase_directive()741 void clear_phase_directive()
742 {
743 CURRENTSECTION->asmpc_phase = -1;
744 }
745