2 * $Id: xlnk.c,v 1.20 2007/11/11 22:35:22 khansen Exp $
4 * Revision 1.20 2007/11/11 22:35:22 khansen
7 * Revision 1.19 2007/08/12 19:01:11 khansen
10 * Revision 1.18 2007/08/07 22:43:01 khansen
13 * Revision 1.17 2007/07/22 13:33:26 khansen
14 * convert tabs to whitespaces
16 * Revision 1.16 2005/01/09 11:19:41 kenth
18 * prints code/data addresses of public symbols when --verbose
20 * Revision 1.15 2005/01/05 09:33:37 kenth
22 * fixed RAM allocator bug
23 * print RAM statistics when --verbose
25 * Revision 1.14 2005/01/05 01:52:19 kenth
28 * Revision 1.13 2005/01/04 21:35:58 kenth
29 * return error code from main() when error count > 0
31 * Revision 1.12 2004/12/29 21:43:55 kenth
34 * Revision 1.11 2004/12/27 06:42:05 kenth
35 * fixed bug in alloc_ram()
37 * Revision 1.10 2004/12/25 02:23:28 kenth
40 * Revision 1.9 2004/12/19 19:58:54 kenth
43 * Revision 1.8 2004/12/18 19:10:39 kenth
44 * relocation improved (I hope)
46 * Revision 1.7 2004/12/18 17:02:00 kenth
47 * CMD_LINE*, CMD_FILE handling, error location printing
48 * CMD_DSW, CMD_DSD gone
50 * Revision 1.6 2004/12/16 13:20:41 kenth
53 * Revision 1.5 2004/12/14 01:50:21 kenth
56 * Revision 1.4 2004/12/11 02:06:18 kenth
59 * Revision 1.3 2004/12/06 04:53:18 kenth
62 * Revision 1.2 2004/06/30 23:38:22 kenth
63 * replaced argp with something else
65 * Revision 1.1 2004/06/30 07:56:04 kenth
68 * Revision 1.1 2004/06/30 07:42:03 kenth
74 * (C) 2004 Kent Hansen
76 * The XORcyst is free software; you can redistribute it and/or modify
77 * it under the terms of the GNU General Public License as published by
78 * the Free Software Foundation; either version 2 of the License, or
79 * (at your option) any later version.
81 * The XORcyst is distributed in the hope that it will be useful,
82 * but WITHOUT ANY WARRANTY; without even the implied warranty of
83 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
84 * GNU General Public License for more details.
86 * You should have received a copy of the GNU General Public License
87 * along with The XORcyst; if not, write to the Free Software
88 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
92 * This is the 6502 linker program. It takes one or more object files generated
93 * by the 6502 assembler program, and then (rough list)
94 * - maps all data labels to physical 6502 RAM
95 * - relocates code to 6502 address space
96 * - resolves external references
97 * - writes everything to a final binary
99 * The input to the linker is a script file which describes the layout and
100 * contents of the final binary.
115 #define SAFE_FREE(m) if ((m) != NULL) { free(m); m = NULL; }
118 * Parses a string to an integer.
122 static int str_to_int(char *s
)
125 return strtol(&s
[1], NULL
, 16);
127 else if (s
[0] == '%') {
128 return strtol(&s
[1], NULL
, 2);
130 return strtol(s
, NULL
, 0);
133 /*--------------------------------------------------------------------------*/
134 /* Argument parsing stuff. */
136 static char program_version
[] = "xlnk 1.5.0";
138 struct tag_arguments
{
144 typedef struct tag_arguments arguments
;
146 /* Argument variables set by arg parser. */
147 static arguments program_args
;
149 /* Long options for getopt_long(). */
150 static struct option long_options
[] = {
151 { "quiet", no_argument
, 0, 'q' },
152 { "silent", no_argument
, 0, 's' },
153 { "verbose", no_argument
, 0, 'v' },
154 { "help", no_argument
, 0, 0 },
155 { "usage", no_argument
, 0, 0 },
156 { "version", no_argument
, 0, 'V' },
160 /* Prints usage message and exits. */
164 Usage: xlnk [-qsvV] [--quiet] [--silent] [--verbose] [--help] [--usage]\n\
170 /* Prints help message and exits. */
174 Usage: xlnk [OPTION...] FILE\n\
175 The XORcyst Linker -- it creates quite a stir\n\
177 -q, -s, --quiet, --silent Don't produce any output\n\
178 -v, --verbose Produce verbose output\n\
179 --help Give this help list\n\
180 --usage Give a short usage message\n\
181 -V, --version Print program version\n\
183 Report bugs to <dev@null>.\n\
188 /* Prints version and exits. */
189 static void version()
191 printf("%s\n", program_version
);
195 /* Parses program arguments. */
197 parse_arguments (int argc
, char **argv
)
200 /* getopt_long stores the option index here. */
203 /* Set default values. */
204 program_args
.silent
= 0;
205 program_args
.verbose
= 0;
206 program_args
.input_file
= NULL
;
209 while ((key
= getopt_long(argc
, argv
, "qsvV", long_options
, &index
)) != -1) {
212 program_args
.silent
= 1;
216 ++program_args
.verbose
;
220 /* Use index to differentiate between options */
221 if (strcmp(long_options
[index
].name
, "usage") == 0) {
224 else if (strcmp(long_options
[index
].name
, "help") == 0) {
234 /* Error message has been printed by getopt_long */
239 /* Forgot to handle a short option, most likely */
245 /* Must be one additional argument, which is the input file. */
246 if (argc
-1 != optind
) {
247 printf("Usage: xlnk [OPTION...] FILE\nTry `xlnk --help' or `xlnk --usage' for more information.\n");
251 program_args
.input_file
= argv
[optind
];
255 /*--------------------------------------------------------------------------*/
256 /* Data structures. */
258 /* Describes a local label in the unit. */
261 char *name
; /* NULL if not exported */
262 int resolved
; /* 0 initially, set to 1 when phys_addr has been assigned */
267 struct tag_xunit
*owner
;
268 unsigned short align
;
272 typedef struct tag_local local
;
274 /* Describes an array of local labels. */
275 struct tag_local_array
281 typedef struct tag_local_array local_array
;
284 * eXtended unit, has extra info built from basic unit ++
288 unit _unit_
; /* NB!!! "Superclass", must be first field for casting to work */
289 local_array data_locals
;
290 local_array code_locals
;
298 typedef struct tag_xunit xunit
;
301 * Describes a 6502 RAM block available for allocation.
303 struct tag_avail_ram_block
305 int start
; /* Start address in 6502 space */
306 int end
; /* End address in 6502 space (not inclusive) */
307 struct tag_avail_ram_block
*next
;
310 typedef struct tag_avail_ram_block avail_ram_block
;
313 struct tag_calc_address_args
319 typedef struct tag_calc_address_args calc_address_args
;
322 struct tag_write_binary_args
328 typedef struct tag_write_binary_args write_binary_args
;
330 /*--------------------------------------------------------------------------*/
332 /** Array containing the units to link. */
334 /* Number of units in above array. */
335 static int unit_count
;
337 /** Holds the current memory address. */
340 /** Hash tables used to lookup symbols. */
341 static hashtab
*label_hash
;
342 static hashtab
*constant_hash
;
343 static hashtab
*unit_hash
;
345 /** Number of errors and warnings during linking */
346 static int err_count
;
347 static int warn_count
;
351 /* Head of the list of available 6502 RAM blocks (for data allocation). */
352 static avail_ram_block
*ram_block_head
= NULL
;
354 /* Total amount of 6502 RAM (bytes) that was registered */
355 static int total_ram
= 0;
358 static int bank_offset
;
359 static int bank_size
;
360 static int bank_origin
;
364 static unsigned char *unit_file
= NULL
; /* length byte followed by chars */
365 static int unit_line
= -1;
367 /*--------------------------------------------------------------------------*/
370 * If the object file contains FILE and LINE bytecodes (assembled with
371 * --debug switch), unit_file and unit_line will contain the current
372 * source location. In that case, this function prints the location.
374 static void maybe_print_location()
378 if (unit_file
!= NULL
) {
379 /* Print source location */
380 len
= unit_file
[0] + 1;
381 str
= (char *)malloc(len
+ 1);
382 strncpy(str
, (char *)&unit_file
[1], len
);
384 fprintf(stderr
, "%s:%d: ", str
, unit_line
);
390 * If the object doesn't contain FILE and LINE bytecodes,
391 * unit_file will be <code>NULL</code>. In that case, this
392 * function prints a tip about reassembling with --debug switch.
394 static void maybe_print_debug_tip()
396 if (unit_file
== NULL
) {
397 fprintf(stderr
, "\treassemble with --debug switch to obtain source location\n");
403 * @param fmt format string for printf
405 static void err(char *fmt
, ...)
410 /* Print error message */
411 fprintf(stderr
, "error: ");
412 maybe_print_location();
413 vfprintf(stderr
, fmt
, ap
);
414 fprintf(stderr
, "\n");
415 maybe_print_debug_tip();
416 /* Increase total error count */
424 * @param fmt format string for printf
426 static void warn(char *fmt
, ...)
431 /* Print warning message */
432 fprintf(stderr
, "warning: ");
433 maybe_print_location();
434 vfprintf(stderr
, fmt
, ap
);
435 fprintf(stderr
, "\n");
436 maybe_print_debug_tip();
437 /* Increase total warning count */
444 * Prints a message if --verbose switch was given.
445 * @param level verbosity level
446 * @param fmt format string for printf
448 static void verbose(int level
, char *fmt
, ...)
452 if (!suppress
&& program_args
.verbose
>= level
) {
453 vfprintf(stdout
, fmt
, ap
);
454 fprintf(stdout
, "\n");
459 /*--------------------------------------------------------------------------*/
460 /* Functions to manage 6502 RAM blocks. */
461 /* The RAM allocator maintains a list of these blocks that are used to
462 map the contents of the units' data segments to memory.
466 * Calculates number of bytes of 6502 RAM left for allocation.
468 static int ram_left()
472 for (sum
= 0, b
= ram_block_head
; b
!= NULL
; b
= b
->next
) {
473 sum
+= b
->end
- b
->start
;
479 * Adds a block of 6502 memory to the list of available memory regions.
480 * When adding multiple blocks they should be added in prioritized order.
481 * @param start Start address of the block
482 * @param end End address of the block (non-inclusive!)
484 static void add_ram_block(int start
, int end
)
487 /* Allocate a block struct */
488 avail_ram_block
*new_block
= (avail_ram_block
*)malloc( sizeof(avail_ram_block
) );
489 if (new_block
!= NULL
) {
491 new_block
->start
= start
;
492 new_block
->end
= end
;
493 new_block
->next
= NULL
;
495 if (ram_block_head
== NULL
) {
497 ram_block_head
= new_block
;
501 for (b
= ram_block_head
; b
->next
!= NULL
; b
= b
->next
) ;
504 verbose(1, " added RAM block: %.4X-%.4X", new_block
->start
, new_block
->end
);
509 * Allocates a chunk of 6502 RAM to a local.
511 * @return 0 if there isn't enough RAM to satisfy the request (fail), 1 otherwise (success)
513 static int alloc_ram(local
*l
)
515 /* Try the available blocks in order. */
516 /* Use the first one that's sufficient. */
518 avail_ram_block
*p
= NULL
;
519 for (b
= ram_block_head
; b
!= NULL
; p
= b
, b
= b
->next
) {
523 /* Check if zero page block required */
524 if (l
->flags
& LABEL_FLAG_ZEROPAGE
) {
525 if (b
->start
>= 0x100) {
526 continue; /* This block is no good */
529 /* Calculate the # of bytes left in this block */
530 left
= b
->end
- b
->start
;
531 /* See if it's enough */
532 if (left
< l
->size
) {
533 continue; /* Not enough, sorry */
535 /* Check if alignment required */
536 if (l
->flags
& LABEL_FLAG_ALIGN
) {
537 pad
= b
->start
& ((1 << l
->align
) - 1);
539 /* This block doesn't match the alignment */
540 /* Break it into two blocks if possible */
541 pad
= (1 << l
->align
) - pad
;
542 pad
= (left
< pad
) ? left
: pad
;
544 n
= (avail_ram_block
*)malloc(sizeof(avail_ram_block
));
546 n
->end
= n
->start
+ pad
;
549 if (b
== ram_block_head
) {
550 ram_block_head
= n
; /* New head */
558 l
->phys_addr
= b
->start
;
559 /* Decrease block size by moving start address ahead */
561 /* If there's no more space left in this block, discard it */
562 if (left
== l
->size
) {
563 /* Remove from linked list */
565 /* Set successor block as new head */
566 ram_block_head
= b
->next
;
572 /* Free associated memory */
575 /* Return with success */
578 /* Couldn't find a block large enough, return with failure */
583 * Frees up memory associated with list of RAM blocks.
585 static void finalize_ram_blocks()
589 for (b
= ram_block_head
; b
!= NULL
; b
= t
) {
595 /*--------------------------------------------------------------------------*/
596 /* Functions to get big-endian values from byte buffer. */
598 /* Gets single byte from buffer and increments index. */
599 static unsigned char get_1(unsigned char *b
, int *i
)
603 /* Gets big-endian short from buffer and increments index. */
604 static unsigned short get_2(unsigned char *b
, int *i
)
606 unsigned short result
= get_1(b
, i
) << 8;
607 result
|= get_1(b
, i
);
610 /* Gets big-endian 24-bit integer from buffer and increments index. */
611 static unsigned int get_3(unsigned char *b
, int *i
)
613 unsigned int result
= get_2(b
, i
) << 8;
614 result
|= get_1(b
, i
);
617 /* Gets big-endian int from buffer and increments index. */
618 /*static unsigned int get_4(unsigned char *b, int *i)
620 unsigned int result = get_2(b, i) << 16;
621 result |= get_2(b, i);
625 /*--------------------------------------------------------------------------*/
628 * Calculates the storage occupied by a CMD_LABEL bytecode's arguments.
630 static int label_cmd_args_size(unsigned char *bytes
)
632 int size
= 1; /* Smallest possible: flag byte */
633 int flags
= bytes
[0];
634 if (flags
& LABEL_FLAG_EXPORT
) { size
+= bytes
[1] + 1 + 1; } /* Length byte + string */
635 if (flags
& LABEL_FLAG_ALIGN
) { size
+= 1; } /* Alignment */
636 if (flags
& LABEL_FLAG_ADDR
) { size
+= 2; } /* Address */
640 /** Signature for procedure to process a bytecode */
641 typedef void (*bytecodeproc
)(unsigned char *, void *);
644 * Walks an array of bytecodes, calling corresponding bytecode handlers
646 * @param bytes Array of bytecodes, terminated by CMD_END
647 * @param handlers Array of bytecode handlers (entries can be NULL)
648 * @param arg Argument passed to bytecode handler, can be anything
650 static void bytecode_walk(unsigned char *bytes
, bytecodeproc
*handlers
, void *arg
)
656 if (bytes
== NULL
) { return; }
660 cmd
= get_1(bytes
, &i
);
662 /* Check if debug command */
666 unit_file
= &bytes
[i
];
667 i
+= get_1(bytes
, &i
) + 1; /* Skip count and array of bytes */
669 case CMD_LINE8
: unit_line
= get_1(bytes
, &i
); break;
670 case CMD_LINE16
: unit_line
= get_2(bytes
, &i
); break;
671 case CMD_LINE24
: unit_line
= get_3(bytes
, &i
); break;
672 case CMD_LINE_INC
: unit_line
++; break;
677 /* Call bytecode handler if one is present */
678 if (handlers
[cmd
-CMD_END
] != NULL
) {
679 handlers
[cmd
-CMD_END
](&bytes
[i
-1], arg
);
681 /* Skip any bytecode arguments */
684 case CMD_BIN8
: i
+= get_1(bytes
, &i
) + 1; break; /* Skip count and array of bytes */
685 case CMD_BIN16
: i
+= get_2(bytes
, &i
) + 1; break; /* Skip count and array of bytes */
686 case CMD_LABEL
: i
+= label_cmd_args_size(&bytes
[i
]); break; /* Skip flag byte and possibly name and alignment */
687 case CMD_INSTR
: i
+= 3; break; /* Skip 6502 opcode and 16-bit expr id */
688 case CMD_DB
: i
+= 2; break; /* Skip 16-bit expr id */
689 case CMD_DW
: i
+= 2; break; /* Skip 16-bit expr id */
690 case CMD_DD
: i
+= 2; break; /* Skip 16-bit expr id */
691 case CMD_DSI8
: i
+= 1; break; /* Skip 8-bit count */
692 case CMD_DSI16
: i
+= 2; break; /* Skip 16-bit count */
693 case CMD_DSB
: i
+= 2; break; /* Skip 16-bit expr id */
697 err("invalid bytecode");
700 } while (cmd
!= CMD_END
);
703 /*--------------------------------------------------------------------------*/
704 /* Functions for expression evaluation. */
707 * Finalizes a constant.
708 * @param c Constant to finalize
710 static void finalize_constant(constant
*c
)
712 if (c
->type
== STRING_CONSTANT
) {
713 SAFE_FREE(c
->string
);
718 * Gets string representation of an operator (OP_*, see objdef.h).
720 * @return String representation of operator
722 static const char *operator_to_string(int op
)
725 case OP_PLUS
: return "+";
726 case OP_MINUS
: return "-";
727 case OP_MUL
: return "*";
728 case OP_DIV
: return "/";
729 case OP_MOD
: return "%";
730 case OP_SHL
: return "<<";
731 case OP_SHR
: return ">>";
732 case OP_AND
: return "&";
733 case OP_OR
: return "|";
734 case OP_XOR
: return "^";
735 case OP_EQ
: return "==";
736 case OP_NE
: return "!=";
737 case OP_LT
: return "<";
738 case OP_GT
: return ">";
739 case OP_LE
: return "<=";
740 case OP_GE
: return ">=";
741 case OP_NOT
: return "!";
742 case OP_NEG
: return "~";
743 case OP_LO
: return "<";
744 case OP_HI
: return ">";
745 case OP_UMINUS
: return "-";
746 case OP_BANK
: return "^";
752 * Evaluates an expression recursively.
753 * The result will either be a integer or string literal, indicating successful
754 * evaluation; or an invalid type indicating that a symbol could not be translated
755 * to a constant (in other words, it could not be resolved). In this case,
756 * result->string contains the name of the symbol which couldn't be evaluated.
757 * @param u The unit where the expression is contained
758 * @param e The expression to evaluate
759 * @param result Pointer to resulting value
761 static void eval_recursive(xunit
*u
, expression
*e
, constant
*result
)
766 constant lhs_result
, rhs_result
;
768 case OPERATOR_EXPRESSION
:
769 switch (e
->op_expr
.operator) {
770 /* Binary operators */
787 /* Evaluate both sides */
788 eval_recursive(u
, e
->op_expr
.lhs
, &lhs_result
);
789 eval_recursive(u
, e
->op_expr
.rhs
, &rhs_result
);
790 /* If either side is unresolved, then result is unresolved. */
791 if ((lhs_result
.type
== -1) || (rhs_result
.type
== -1)) {
794 /* If both sides are integer, then result is integer. */
795 else if ((lhs_result
.type
== INTEGER_CONSTANT
) &&
796 (rhs_result
.type
== INTEGER_CONSTANT
)) {
797 result
->type
= INTEGER_CONSTANT
;
798 /* Perform the proper operation to obtain result. */
799 switch (e
->op_expr
.operator) {
800 case OP_PLUS
: result
->integer
= lhs_result
.integer
+ rhs_result
.integer
; break;
801 case OP_MINUS
: result
->integer
= lhs_result
.integer
- rhs_result
.integer
; break;
802 case OP_MUL
: result
->integer
= lhs_result
.integer
* rhs_result
.integer
; break;
803 case OP_DIV
: result
->integer
= lhs_result
.integer
/ rhs_result
.integer
; break;
804 case OP_MOD
: result
->integer
= lhs_result
.integer
% rhs_result
.integer
; break;
805 case OP_SHL
: result
->integer
= lhs_result
.integer
<< rhs_result
.integer
; break;
806 case OP_SHR
: result
->integer
= lhs_result
.integer
>> rhs_result
.integer
; break;
807 case OP_AND
: result
->integer
= lhs_result
.integer
& rhs_result
.integer
; break;
808 case OP_OR
: result
->integer
= lhs_result
.integer
| rhs_result
.integer
; break;
809 case OP_XOR
: result
->integer
= lhs_result
.integer
^ rhs_result
.integer
; break;
810 case OP_EQ
: result
->integer
= lhs_result
.integer
== rhs_result
.integer
; break;
811 case OP_NE
: result
->integer
= lhs_result
.integer
!= rhs_result
.integer
; break;
812 case OP_LT
: result
->integer
= lhs_result
.integer
< rhs_result
.integer
; break;
813 case OP_GT
: result
->integer
= lhs_result
.integer
> rhs_result
.integer
; break;
814 case OP_LE
: result
->integer
= lhs_result
.integer
<= rhs_result
.integer
; break;
815 case OP_GE
: result
->integer
= lhs_result
.integer
>= rhs_result
.integer
; break;
818 /* If both sides are string... */
819 else if ((lhs_result
.type
== STRING_CONSTANT
) &&
820 (rhs_result
.type
== STRING_CONSTANT
)) {
821 switch (e
->op_expr
.operator) {
824 result
->string
= (char *)malloc(strlen(lhs_result
.string
)+strlen(rhs_result
.string
)+1);
825 if (result
->string
!= NULL
) {
826 strcpy(result
->string
, lhs_result
.string
);
827 strcat(result
->string
, rhs_result
.string
);
828 result
->type
= STRING_CONSTANT
;
832 /* String comparison: using strcmp() */
833 case OP_EQ
: result
->integer
= strcmp(lhs_result
.string
, rhs_result
.string
) == 0; break;
834 case OP_NE
: result
->integer
= strcmp(lhs_result
.string
, rhs_result
.string
) != 0; break;
835 case OP_LT
: result
->integer
= strcmp(lhs_result
.string
, rhs_result
.string
) < 0; break;
836 case OP_GT
: result
->integer
= strcmp(lhs_result
.string
, rhs_result
.string
) > 0; break;
837 case OP_LE
: result
->integer
= strcmp(lhs_result
.string
, rhs_result
.string
) <= 0; break;
838 case OP_GE
: result
->integer
= strcmp(lhs_result
.string
, rhs_result
.string
) >= 0; break;
841 /* Not defined operator for string operation... */
846 /* Error, operands are incompatible */
848 err("incompatible operands to `%s' in expression", operator_to_string(e
->op_expr
.operator) );
850 /* Discard the operands */
851 finalize_constant(&lhs_result
);
852 finalize_constant(&rhs_result
);
853 break; /* Binary operator */
855 /* Unary operators */
861 /* Evaluate the single operand */
862 eval_recursive(u
, e
->op_expr
.lhs
, &lhs_result
);
863 /* If operand is unresolved then result is unresolved. */
864 if (lhs_result
.type
== -1) {
867 /* If operand is integer then result is integer. */
868 else if (lhs_result
.type
== INTEGER_CONSTANT
) {
869 result
->type
= INTEGER_CONSTANT
;
870 /* Perform the proper operation to obtain result. */
871 switch (e
->op_expr
.operator) {
872 case OP_NOT
: result
->integer
= !lhs_result
.integer
; break;
873 case OP_NEG
: result
->integer
= ~lhs_result
.integer
; break;
874 case OP_LO
: result
->integer
= lhs_result
.integer
& 0xFF; break;
875 case OP_HI
: result
->integer
= (lhs_result
.integer
>> 8) & 0xFF; break;
876 case OP_UMINUS
: result
->integer
= -lhs_result
.integer
; break;
880 /* Error, invalid operand */
881 err("incompatible operand to `%s' in expression", operator_to_string(e
->op_expr
.operator) );
884 /* Discard the operand */
885 finalize_constant(&lhs_result
);
886 break; /* Unary operator */
889 switch (e
->op_expr
.lhs
->type
) {
890 case LOCAL_EXPRESSION
:
891 /* Simple, it must be in the same (current) bank */
892 result
->integer
= bank_id
;
893 result
->type
= INTEGER_CONSTANT
;
896 case EXTERNAL_EXPRESSION
:
897 /* Get the name of the external */
898 s
= u
->_unit_
.externals
[e
->op_expr
.lhs
->extrn_id
].name
;
900 if ((l
= (local
*)hashtab_get(label_hash
, s
)) != NULL
) {
902 result
->integer
= l
->owner
->bank_id
;
903 result
->type
= INTEGER_CONSTANT
;
905 else if ((c
= (constant
*)hashtab_get(constant_hash
, s
)) != NULL
) {
906 /* It's a constant */
907 result
->integer
= ((xunit
*)c
->unit
)->bank_id
;
908 result
->type
= INTEGER_CONSTANT
;
923 case INTEGER_EXPRESSION
:
924 /* Copy value to result */
925 result
->type
= INTEGER_CONSTANT
;
926 result
->integer
= e
->integer
;
929 case STRING_EXPRESSION
:
930 /* Copy value to result */
931 result
->string
= (char *)malloc(strlen(e
->string
) + 1);
932 if (result
->string
!= NULL
) {
933 strcpy(result
->string
, e
->string
);
934 result
->type
= STRING_CONSTANT
;
938 case LOCAL_EXPRESSION
:
939 if (e
->local_id
>= u
->data_locals
.size
) {
940 /* It's a code local */
941 l
= &u
->code_locals
.entries
[e
->local_id
- u
->data_locals
.size
];
944 /* It's a data local */
945 l
= &u
->data_locals
.entries
[e
->local_id
];
947 /* Test if it's resolved */
949 /* Copy address to result */
950 result
->type
= INTEGER_CONSTANT
;
951 result
->integer
= l
->phys_addr
;
954 /* Not resolved (yet, at least) */
959 case EXTERNAL_EXPRESSION
:
960 /* Get the name of the external */
961 s
= u
->_unit_
.externals
[e
->extrn_id
].name
;
963 if ((l
= (local
*)hashtab_get(label_hash
, s
)) != NULL
) {
965 /* Test if it's resolved */
967 /* Copy address to result */
968 result
->type
= INTEGER_CONSTANT
;
969 result
->integer
= l
->phys_addr
;
972 /* Not resolved (yet) */
976 else if ((c
= (constant
*)hashtab_get(constant_hash
, s
)) != NULL
) {
977 /* It's a constant */
978 /* Copy value to result */
980 case INTEGER_CONSTANT
:
981 result
->type
= INTEGER_CONSTANT
;
982 result
->integer
= c
->integer
;
985 case STRING_CONSTANT
:
986 result
->string
= (char *)malloc(strlen(c
->string
) + 1);
987 if (result
->string
!= NULL
) {
988 strcpy(result
->string
, c
->string
);
989 result
->type
= STRING_CONSTANT
;
997 err("unknown symbol `%s' referenced from %s", s
, u
->_unit_
.name
);
1002 /* Copy current PC to result */
1003 result
->type
= INTEGER_CONSTANT
;
1004 result
->integer
= pc
;
1010 * Evaluates an expression.
1011 * @param u The unit where the expression is contained
1012 * @param exid The unique ID of the expression
1013 * @param result Where to store the result of the evaluation
1015 static void eval_expression(xunit
*u
, int exid
, constant
*result
)
1017 /* Get the expression with id exid */
1018 expression
*exp
= u
->_unit_
.expressions
[exid
];
1019 /* Evaluate recursively */
1020 eval_recursive(u
, exp
, result
);
1023 /*--------------------------------------------------------------------------*/
1024 /* Functions for incrementing PC, with error handling for wraparound. */
1027 * Increases PC by amount.
1028 * Issues error if the PC wraps around.
1030 static void inc_pc(int amount
, void *arg
)
1032 calc_address_args
*aargs
;
1033 /* Check for 16-bit overflow */
1034 if ((pc
<= 0x10000) && ((pc
+amount
) > 0x10000)) {
1035 aargs
= (calc_address_args
*)arg
;
1036 err("PC went beyond 64K when linking `%s'", aargs
->xu
->_unit_
.name
);
1043 * Increases PC by 8-bit value immediately following bytecode command.
1045 static void inc_pc_count8(unsigned char *b
, void *arg
)
1048 inc_pc( get_1(b
, &i
) + 1, arg
);
1052 * Increases PC by 16-bit value immediately following bytecode command.
1054 static void inc_pc_count16(unsigned char *b
, void *arg
)
1057 inc_pc( get_2(b
, &i
) + 1, arg
);
1061 * Increases PC by 1.
1063 static void inc_pc_1(unsigned char *b
, void *arg
)
1069 * Increases PC by 2.
1071 static void inc_pc_2(unsigned char *b
, void *arg
)
1077 * Increases PC by 4.
1079 static void inc_pc_4(unsigned char *b
, void *arg
)
1085 * Increases PC according to size of define data command.
1087 static void inc_pc_dsb(unsigned char *b
, void *arg
)
1091 calc_address_args
*args
= (calc_address_args
*)arg
;
1093 /* Get expression ID */
1094 exid
= get_2(b
, &i
);
1095 /* Evaluate expression */
1096 eval_expression(args
->xu
, exid
, &c
);
1097 /* Handle the result */
1098 if (c
.type
== INTEGER_CONSTANT
) {
1099 /* An array of bytes will be located here */
1100 /* Advance PC appropriately */
1101 inc_pc( c
.integer
, arg
);
1103 else if (c
.type
== STRING_CONSTANT
) {
1104 /* Error, doesn't make sense here */
1105 err("unexpected string operand (`%s') to storage directive", c
.string
);
1108 /* Error, unresolved */
1109 //err("unresolved symbol");
1112 finalize_constant(&c
);
1116 * Increments PC according to the length of this instruction.
1118 static void inc_pc_instr(unsigned char *b
, void *arg
)
1121 unsigned char op
, t
;
1123 calc_address_args
*args
= (calc_address_args
*)arg
;
1127 /* Get expression ID */
1128 exid
= get_2(b
, &i
);
1130 eval_expression(args
->xu
, exid
, &c
);
1131 /* Handle the result */
1132 if (c
.type
== INTEGER_CONSTANT
) {
1133 /* See if it can be reduced to ZP instruction */
1134 if ((c
.integer
< 0x100) &&
1135 ((t
= opcode_zp_equiv(op
)) != 0xFF)) {
1136 /* replace op by ZP-version */
1141 else if (c
.type
== STRING_CONSTANT
) {
1142 /* Error, string operand doesn't make sense here */
1143 err("invalid instruction operand (string)");
1146 /* Address not available yet (forward reference). */
1147 //err("unresolved symbol");
1150 inc_pc( opcode_length(op
), arg
);
1153 /*--------------------------------------------------------------------------*/
1154 /* Functions for writing pure 6502 binary from bytecodes. */
1157 * Writes an array of bytes.
1159 static void write_bin8(unsigned char *b
, void *arg
)
1163 write_binary_args
*args
= (write_binary_args
*)arg
;
1164 /* Get 8-bit count */
1166 count
= get_1(b
, &i
) + 1;
1168 fwrite(&b
[i
], 1, count
, args
->fp
);
1170 inc_pc( count
, arg
);
1174 * Writes an array of bytes.
1176 static void write_bin16(unsigned char *b
, void *arg
)
1180 write_binary_args
*args
= (write_binary_args
*)arg
;
1181 /* Get 16-bit count */
1183 count
= get_2(b
, &i
) + 1;
1185 fwrite(&b
[i
], 1, count
, args
->fp
);
1187 inc_pc( count
, arg
);
1191 * Writes an instruction.
1193 static void write_instr(unsigned char *b
, void *arg
)
1199 write_binary_args
*args
= (write_binary_args
*)arg
;
1203 /* Get expression ID */
1204 exid
= get_2(b
, &i
);
1205 /* Evaluate expression */
1206 eval_expression(args
->xu
, exid
, &c
);
1208 /* Write the opcode */
1209 fputc(op
, args
->fp
);
1211 if (opcode_length(op
) == 2) {
1212 /* Operand must fit in 1 byte */
1213 /* Check if it's a relative jump */
1223 /* Calculate difference between target and address of next instruction */
1224 c
.integer
= c
.integer
- (pc
+ 2);
1225 /* Make sure jump is in range */
1226 if ( (c
.integer
< -128) || (c
.integer
> 127) ) {
1227 err("branch out of range");
1229 /* Make it a byte value */
1233 if (c
.integer
>= 0x100) {
1234 err("instruction operand doesn't fit in 1 byte");
1238 fputc(c
.integer
, args
->fp
);
1242 /* Operand must fit in 2 bytes */
1243 if (c
.integer
>= 0x10000) {
1244 err("instruction operand doesn't fit in 2 bytes");
1247 /* Write it, low byte first */
1248 fputc(c
.integer
, args
->fp
);
1249 fputc(c
.integer
>> 8, args
->fp
);
1253 inc_pc( opcode_length(op
), arg
);
1257 * Writes a byte, word or dword.
1259 static void write_dx(unsigned char *b
, void *arg
)
1264 write_binary_args
*args
= (write_binary_args
*)arg
;
1265 /* Get expression ID */
1267 exid
= get_2(b
, &i
);
1268 /* Evaluate expression */
1269 eval_expression(args
->xu
, exid
, &c
);
1271 if (c
.type
== INTEGER_CONSTANT
) {
1272 /* Write low byte */
1273 fputc(c
.integer
, args
->fp
);
1274 /* If 2+ bytes, write high ones */
1277 if (c
.integer
> 0xFF) {
1278 warn("`.DB' operand $%X out of range; truncated", c
.integer
);
1283 fputc(c
.integer
>> 8, args
->fp
);
1284 if (c
.integer
> 0xFFFF) {
1285 warn("`.DW' operand $%X out of range; truncated", c
.integer
);
1290 fputc(c
.integer
>> 8, args
->fp
);
1291 fputc(c
.integer
>> 16, args
->fp
);
1292 fputc(c
.integer
>> 24, args
->fp
);
1297 case CMD_DB
: inc_pc( 1, arg
); break;
1298 case CMD_DW
: inc_pc( 2, arg
); break;
1299 case CMD_DD
: inc_pc( 4, arg
); break;
1302 else if (c
.type
== STRING_CONSTANT
) {
1303 /* Write sequence of characters */
1304 for (i
=0; i
<strlen(c
.string
); i
++) {
1305 /* Write low byte */
1306 fputc(c
.string
[i
], args
->fp
);
1307 /* If 2+ bytes, write high ones */
1321 case CMD_DB
: inc_pc( 1, arg
); break;
1322 case CMD_DW
: inc_pc( 2, arg
); break;
1323 case CMD_DD
: inc_pc( 4, arg
); break;
1328 finalize_constant(&c
);
1332 * Writes a series of zeroes.
1334 static void write_dsi8(unsigned char *b
, void *arg
)
1338 write_binary_args
*args
= (write_binary_args
*)arg
;
1339 /* Get 8-bit count */
1341 count
= get_1(b
, &i
) + 1;
1343 for (i
=0; i
<count
; i
++) {
1347 inc_pc( count
, arg
);
1351 * Writes a series of zeroes.
1353 static void write_dsi16(unsigned char *b
, void *arg
)
1357 write_binary_args
*args
= (write_binary_args
*)arg
;
1358 /* Get 16-bit count */
1360 count
= get_2(b
, &i
) + 1;
1362 for (i
=0; i
<count
; i
++) {
1366 inc_pc( count
, arg
);
1370 * Writes a series of zeroes.
1372 static void write_dsb(unsigned char *b
, void *arg
)
1377 write_binary_args
*args
= (write_binary_args
*)arg
;
1378 /* Get expression ID */
1380 exid
= get_2(b
, &i
);
1381 /* Evaluate expression */
1382 eval_expression(args
->xu
, exid
, &c
);
1383 if (c
.integer
< 0) {
1384 err("negative count");
1386 else if (c
.integer
> 0) {
1388 for (i
=0; i
<c
.integer
; i
++) {
1392 inc_pc( c
.integer
, arg
);
1397 * Writes a code segment as fully native 6502 code.
1398 * @param fp File handle
1399 * @param u Unit whose code to write
1401 static void write_as_binary(FILE *fp
, xunit
*u
)
1403 write_binary_args args
;
1404 /* Table of callback functions for our purpose. */
1405 bytecodeproc handlers
[] =
1408 write_bin8
, /* CMD_BIN8 */
1409 write_bin16
, /* CMD_BIN16 */
1410 NULL
, /* CMD_LABEL */
1411 write_instr
, /* CMD_INSTR */
1412 write_dx
, /* CMD_DB */
1413 write_dx
, /* CMD_DW */
1414 write_dx
, /* CMD_DD */
1415 write_dsi8
, /* CMD_DSI8 */
1416 write_dsi16
, /* CMD_DSI16 */
1417 write_dsb
/* CMD_DSB */
1423 pc
= u
->code_origin
;
1425 bytecode_walk(u
->_unit_
.codeseg
.bytes
, handlers
, (void *)&args
);
1428 #define XLNK_NO_DEBUG
1429 #ifndef XLNK_NO_DEBUG
1431 /*--------------------------------------------------------------------------*/
1432 /* Functions for debugging bytecodes. */
1435 * Gets string representation of bytecode command.
1437 * @return String representation ("CMD_*")
1439 static const char *bytecode_to_string(unsigned char cmd
)
1442 case CMD_FILE
: return "CMD_FILE";
1443 case CMD_LINE8
: return "CMD_LINE8";
1444 case CMD_LINE16
:return "CMD_LINE16";
1445 case CMD_LINE24
:return "CMD_LINE24";
1446 case CMD_LINE_INC
: return "CMD_LINE_INC";
1447 case CMD_END
: return "CMD_END";
1448 case CMD_BIN8
: return "CMD_BIN8";
1449 case CMD_BIN16
: return "CMD_BIN16";
1450 case CMD_LABEL
: return "CMD_LABEL";
1451 case CMD_INSTR
: return "CMD_INSTR";
1452 case CMD_DB
: return "CMD_DB";
1453 case CMD_DW
: return "CMD_DW";
1454 case CMD_DD
: return "CMD_DD";
1455 case CMD_DSI8
: return "CMD_DSI8";
1456 case CMD_DSI16
: return "CMD_DSI16";
1457 case CMD_DSB
: return "CMD_DSB";
1459 return "bytecode_to_string: invalid bytecode";
1464 * @param b Bytecodes
1465 * @param arg Not used
1467 static void print_it(unsigned char *b
, void *arg
)
1469 printf("%s\n", bytecode_to_string(b
[0]) );
1474 * @param bytes Bytecodes
1476 static void print_bytecodes(unsigned char *bytes
)
1478 bytecodeproc handlers
[] =
1480 print_it
,print_it
,print_it
,print_it
,print_it
,
1481 print_it
,print_it
,print_it
,print_it
,print_it
,
1482 print_it
,print_it
,print_it
1484 bytecode_walk(bytes
, handlers
, NULL
);
1491 static void print_unit(unit
*u
)
1493 print_bytecodes(u
->dataseg
.bytes
);
1494 print_bytecodes(u
->codeseg
.bytes
);
1497 #endif /* !XLNK_NO_DEBUG */
1499 /*--------------------------------------------------------------------------*/
1500 /* Functions for managing arrays of unit locals. */
1503 * Creates array of locals.
1504 * @param size Number of locals
1505 * @param la Local array
1507 static void create_local_array(int size
, local_array
*la
)
1510 /* Allocate space for entries */
1512 la
->entries
= (local
*)malloc(sizeof(local
) * size
);
1520 * Finalizes array of locals.
1522 static void finalize_local_array(local_array
*la
)
1525 /* Free entry attributes */
1526 for (i
=0; i
<la
->size
; i
++) {
1527 SAFE_FREE(la
->entries
[i
].name
);
1529 /* Free array itself */
1530 SAFE_FREE(la
->entries
);
1533 /*--------------------------------------------------------------------------*/
1534 /* Functions for counting and registering locals in a unit. */
1535 /* In bytecode expressions, locals are referred to by their index.
1536 In order to not have to go through the bytecodes every time to
1537 find a label definition, the following functions build an array
1538 of structures that can be indexed by the local ID to obtain its
1543 * Counts this local.
1545 static void count_one_local(unsigned char *b
, void *arg
)
1547 /* Argument points to the counter */
1548 int *count
= (int *)arg
;
1549 /* Increment count */
1554 * Counts the number of locals (labels) in an array of bytecodes.
1555 * @param b Bytecodes, terminated by CMD_END
1556 * @return Number of locals counted
1558 static int count_locals(unsigned char *b
)
1561 /* Table of callback functions for our purpose. */
1562 bytecodeproc handlers
[] =
1565 NULL
, /* CMD_BIN8 */
1566 NULL
, /* CMD_BIN16 */
1567 count_one_local
, /* CMD_LABEL */
1568 NULL
, /* CMD_INSTR */
1572 NULL
, /* CMD_DSI8 */
1573 NULL
, /* CMD_DSI16 */
1578 /* Count the locals now */
1579 bytecode_walk(b
, handlers
, (void *)&count
);
1580 /* Return the number of locals counted */
1585 * Variable that points to the unit that locals are being registered for.
1587 static xunit
*reg_unit
= NULL
;
1590 * Puts this local into array of locals for current unit.
1592 static void register_one_local(unsigned char *b
, void *arg
)
1596 /* Argument points to a pointer which points to the local struct to fill in */
1597 local
**lpptr
= (local
**)arg
;
1598 local
*lptr
= *lpptr
;
1599 /* Initialize some fields */
1601 lptr
->ref_count
= 0;
1604 lptr
->owner
= reg_unit
;
1606 lptr
->flags
= get_1(b
, &i
);
1607 /* Test export flag */
1608 if (lptr
->flags
& LABEL_FLAG_EXPORT
) {
1609 /* Get the length of the name */
1610 len
= get_1(b
, &i
) + 1;
1611 /* Allocate space for name */
1612 lptr
->name
= (char *)malloc( len
+ 1 );
1613 if (lptr
->name
!= NULL
) {
1614 /* Copy name from bytecodes */
1615 memcpy(lptr
->name
, &b
[i
], len
);
1616 /* Zero-terminate string */
1617 lptr
->name
[len
] = '\0';
1621 /* Test align flag */
1622 if (lptr
->flags
& LABEL_FLAG_ALIGN
) {
1623 lptr
->align
= get_1(b
, &i
);
1625 /* Test address flag */
1626 if (lptr
->flags
& LABEL_FLAG_ADDR
) {
1627 lptr
->phys_addr
= get_2(b
, &i
);
1631 if (program_args
.verbose
) {
1632 verbose(1, " %s align=%d resolved=%d",
1633 lptr
->name
? lptr
->name
: "(anonymous)",
1634 lptr
->align
, lptr
->resolved
);
1637 /* Point to next local in array */
1642 * Puts all locals found in the array of bytecodes into array.
1643 * @param b Bytecodes, terminated by CMD_END
1644 * @param la Pointer to array to receive locals
1645 * @param xu Owner unit
1647 static void register_locals(unsigned char *b
, local_array
*la
, xunit
*xu
)
1651 /* Table of callback functions for our purpose. */
1652 bytecodeproc handlers
[] =
1655 NULL
, /* CMD_BIN8 */
1656 NULL
, /* CMD_BIN16 */
1657 register_one_local
, /* CMD_LABEL */
1658 NULL
, /* CMD_INSTR */
1662 NULL
, /* CMD_DSI8 */
1663 NULL
, /* CMD_DSI16 */
1666 /* Create array of locals */
1667 create_local_array(count_locals(b
), la
);
1673 bytecode_walk(b
, handlers
, (void *)lpptr
);
1676 /*--------------------------------------------------------------------------*/
1677 /* Functions for entering exported symbols into proper hash table. */
1680 * Enters an exported symbol into a hash table.
1681 * @param tab Hash table to enter it into
1684 * @param u Owner unit
1686 static void enter_exported_symbol(hashtab
*tab
, void *key
, void *data
, unit
*u
)
1688 /* Make sure symbol doesn't already exist */
1689 if ((hashtab_get(label_hash
, key
) != NULL
)
1690 || (hashtab_get(constant_hash
, key
) != NULL
) ) {
1691 /* Error, duplicate symbol */
1692 err("duplicate symbol `%s' exported from unit `%s'", (char *)key
, u
->name
);
1695 verbose(1, " %s", (char*)key
);
1697 hashtab_put(tab
, key
, data
);
1702 * Enters all constants in a unit into the proper hash table.
1703 * @param u Unit whose constants to enter
1705 static void enter_exported_constants(unit
*u
)
1709 /* Go through all constants in unit */
1710 for (i
=0; i
<u
->const_count
; i
++) {
1711 c
= &u
->constants
[i
];
1712 enter_exported_symbol(constant_hash
, (void *)c
->name
, (void *)c
, u
);
1717 * Enters locals which should be globally visible into the proper hash table.
1718 * @param la Array of locals
1719 * @param u Owner unit
1721 static void enter_exported_locals(local_array
*la
, unit
*u
)
1725 /* Go through all locals */
1726 for (i
=0; i
<la
->size
; i
++) {
1727 l
= &la
->entries
[i
];
1728 /* If it has a name, it is exported */
1729 if (l
->name
!= NULL
) {
1730 enter_exported_symbol(label_hash
, (void *)l
->name
, (void *)l
, u
);
1735 /*--------------------------------------------------------------------------*/
1736 /* Functions for calculating addresses of data labels in a unit. */
1739 * Sets the virtual address of this local to current PC value.
1741 static void set_data_address(unsigned char *b
, void *arg
)
1743 calc_address_args
*args
= (calc_address_args
*)arg
;
1745 local
*l
= &args
->xu
->data_locals
.entries
[args
->index
];
1747 /* Set the virtual address */
1749 verbose(2, " %.4X %s", l
->virt_addr
, l
->name
? l
->name
: "");
1751 /* Increase label index */
1756 * Calculates addresses of labels in a data segment relative to 0.
1757 * Only a small set of bytecode commands are allowed in a data segment:
1758 * - label (which we want to assign a virtual address)
1759 * - storage (constant or variable)
1761 static void calc_data_addresses(xunit
*u
)
1763 calc_address_args args
;
1764 /* Table of callback functions for our purpose. */
1765 bytecodeproc handlers
[] =
1768 NULL
, /* CMD_BIN8 */
1769 NULL
, /* CMD_BIN16 */
1770 set_data_address
, /* CMD_LABEL */
1771 NULL
, /* CMD_INSTR */
1775 inc_pc_count8
, /* CMD_DSI8 */
1776 inc_pc_count16
, /* CMD_DSI16 */
1777 inc_pc_dsb
/* CMD_DSB */
1784 verbose(1, " %s", u
->_unit_
.name
);
1786 bytecode_walk(u
->_unit_
.dataseg
.bytes
, handlers
, (void *)&args
);
1787 /* Store the end address, which is the total size of data */
1791 /*--------------------------------------------------------------------------*/
1793 /* Constructs 32-bit sort key for local. */
1794 #define SORT_KEY(l) (unsigned long)((((l)->flags & LABEL_FLAG_ZEROPAGE) << 30) | ((l)->align << 24) | (0x10000-(l)->size))
1797 * Array is sorted from high to low value.
1799 static int label_partition(local
**a
, int p
, int r
)
1807 for (j
=p
; j
<r
; j
++) {
1808 if (SORT_KEY(a
[j
]) >= x
) {
1822 * Quicksort implementation used to sort array of pointers to locals.
1824 static void label_qsort(local
**a
, int p
, int r
)
1828 q
= label_partition(a
, p
, r
);
1829 label_qsort(a
, p
, q
-1);
1830 label_qsort(a
, q
+1, r
);
1835 * Maps all data labels to 6502 RAM locations.
1836 * This is a very important function. It takes all the data labels from all
1837 * the loaded units and attempts to assign them unique physical addresses.
1838 * The list of target RAM blocks given in the linker script is the premise.
1840 static void map_data_to_ram()
1843 local
**total_order
;
1846 /* Use a bit array to keep track of allocations,
1847 to ensure that there is no overlap */
1848 unsigned char *allocated
;
1849 int ram_base
, ram_end
;
1852 ram_base
= 10000000;
1853 ram_end
= -10000000;
1854 for (b
= ram_block_head
; b
!= NULL
; b
= b
->next
) {
1855 if (b
->start
< ram_base
)
1856 ram_base
= b
->start
;
1857 if (b
->end
> ram_end
)
1861 allocated
= (unsigned char *)malloc(((ram_end
- ram_base
) + 7) / 8);
1862 memset(allocated
, 0, ((ram_end
- ram_base
) + 7) / 8);
1863 /* Calculate total number of labels to map */
1865 for (i
=0; i
<unit_count
; i
++) {
1866 count
+= units
[i
].data_locals
.size
;
1868 /* Put pointers to all data labels in one big array */
1869 total_order
= (local
**)malloc( count
* sizeof(local
*) );
1870 for (i
=0, k
=0; i
<unit_count
; i
++) {
1873 la
= &units
[i
].data_locals
;
1874 for (j
=0; j
<la
->size
; j
++) {
1876 /* Use virtual addresses to calculate size from this label to next */
1877 if (j
== la
->size
-1) {
1878 size
= units
[i
].data_size
;
1881 size
= la
->entries
[j
+1].virt_addr
;
1883 la
->entries
[j
].size
= size
- la
->entries
[j
].virt_addr
;
1884 /* Put pointer in array */
1885 total_order
[k
++] = &la
->entries
[j
];
1889 label_qsort(total_order
, 0, count
-1);
1891 for (i
=0; i
<count
; i
++) {
1893 /* Try to allocate it */
1894 if (alloc_ram(l
) == 1) {
1895 /* Good, label mapped successfully */
1897 verbose(1, " %.4X-%.4X %s (%s)", l
->phys_addr
,
1898 l
->phys_addr
+ l
->size
-1, l
->name
? l
->name
: "",
1899 l
->owner
->_unit_
.name
);
1901 /* Verify that there's no overlap with other variable */
1903 for (a
= l
->phys_addr
; a
< l
->phys_addr
+ l
->size
; ++a
) {
1904 assert((allocated
[(a
- ram_base
) / 8] & (1 << (a
& 7))) == 0);
1905 allocated
[(a
- ram_base
) / 8] |= 1 << (a
& 7);
1910 /* Error, couldn't allocate */
1911 err("out of 6502 RAM while allocating unit `%s'", l
->owner
->_unit_
.name
);
1919 /*--------------------------------------------------------------------------*/
1920 /* Functions for calculating offsets of code labels in a unit. */
1923 * Sets the address of this code label to current PC.
1925 static void set_code_address(unsigned char *b
, void *arg
)
1927 calc_address_args
*args
= (calc_address_args
*)arg
;
1929 local
*l
= &args
->xu
->code_locals
.entries
[args
->index
];
1931 /* Set the physical address to current PC */
1934 if (program_args
.verbose
) {
1935 fprintf(stdout
, " %.4X %s (%s)\n", l
->phys_addr
,
1936 l
->name
? l
->name
: "", l
->owner
->_unit_
.name
);
1939 /* Increase label index */
1944 * Calculates addresses of code labels in a segment.
1945 * NOTE: Only the virtual addresses (relative to 0) are calculated.
1946 * The labels then need to be relocated to obtain the physical address (see below).
1949 static void calc_code_addresses(xunit
*u
)
1951 calc_address_args args
;
1952 /* Table of callback functions for our purpose. */
1953 bytecodeproc handlers
[] =
1956 inc_pc_count8
, /* CMD_BIN8 */
1957 inc_pc_count16
, /* CMD_BIN16 */
1958 set_code_address
, /* CMD_LABEL */
1959 inc_pc_instr
, /* CMD_INSTR */
1960 inc_pc_1
, /* CMD_DB -- TODO, error if string */
1961 inc_pc_2
, /* CMD_DW */
1962 inc_pc_4
, /* CMD_DD */
1963 inc_pc_count8
, /* CMD_DSI8 */
1964 inc_pc_count16
, /* CMD_DSI16 */
1965 inc_pc_dsb
/* CMD_DSB */
1971 bytecode_walk(u
->_unit_
.codeseg
.bytes
, handlers
, (void *)&args
);
1972 /* Store the total size of code */
1973 u
->code_size
= pc
- u
->code_origin
;
1976 /*--------------------------------------------------------------------------*/
1979 * Issues a script error.
1981 static void scripterr(script
*s
, script_command
*c
, char *fmt
, ...)
1987 /* Print error message */
1988 fprintf(stderr
, "error: %s:%d: `%s': ", s
->name
, c
->line
, script_command_type_to_string(c
->type
) );
1989 vfprintf(stderr
, fmt
, ap
);
1990 fprintf(stderr
, "\n");
1991 /* Increase error count */
1997 #define require_arg(s, c, a, d) { \
1998 d = script_get_command_arg(c, a); \
2000 scripterr(s, c, "missing argument `%s'", a); \
2005 #define require_arg_in_range(s, c, a, v, l, h) { \
2006 if (((v) < (l)) || ((v) > (h))) { \
2007 scripterr(s, c, "value of argument `%s' is out of range", a); \
2012 /*--------------------------------------------------------------------------*/
2013 /* Functions for registering RAM blocks in script. */
2016 * Registers one RAM block based on 'ram' script command.
2017 * @param s Linker script
2018 * @param c Command of type RAM_COMMAND
2019 * @param arg Not used
2021 static void register_one_ram_block(script
*s
, script_command
*c
, void *arg
)
2028 require_arg(s
, c
, "start", start_str
);
2029 require_arg(s
, c
, "end", end_str
);
2030 /* Convert to integers */
2031 start
= str_to_int(start_str
);
2032 end
= str_to_int(end_str
);
2033 /* Check that they are sane */
2034 require_arg_in_range(s
, c
, "start", start
, 0x0000, 0xFFFF);
2035 require_arg_in_range(s
, c
, "end", end
, 0x0000, 0xFFFF);
2037 scripterr(s
, c
, "`end' is smaller than `start'");
2040 add_ram_block(start
, end
);
2044 * Registers RAM blocks based on 'ram' commands in a script.
2045 * @param sc Linker script
2047 static void register_ram_blocks(script
*sc
)
2049 /* Table of mappings for our purpose */
2050 static script_commandprocmap map
[] = {
2051 { RAM_COMMAND
, register_one_ram_block
},
2052 { BAD_COMMAND
, NULL
}
2055 script_walk(sc
, map
, NULL
);
2056 /* Calculate total RAM size */
2057 total_ram
= ram_left();
2060 /*--------------------------------------------------------------------------*/
2061 /* Functions for loading and initial processing of units in script. */
2064 * Registers (parses etc.) one unit based on 'link' script command.
2065 * @param s Linker script
2066 * @param c Command of type LINK_COMMAND
2067 * @param arg Pointer to unit index
2069 static void register_one_unit(script
*s
, script_command
*c
, void *arg
)
2074 /* Get unit filename */
2075 require_arg(s
, c
, "file", file
);
2076 /* arg is pointer to unit index */
2078 /* Get pointer to xunit to fill in */
2080 /* Read basic unit from file */
2081 if (unit_read(file
, &xu
->_unit_
) == 0) {
2082 /* Something bad happened when trying to read unit */
2083 scripterr(s
, c
, "failed to load unit `%s'", file
);
2088 verbose(1, " unit `%s' loaded", file
);
2089 /* Register locals for both segments */
2090 verbose(1, " registering local symbols...");
2091 register_locals(xu
->_unit_
.dataseg
.bytes
, &xu
->data_locals
, xu
);
2092 register_locals(xu
->_unit_
.codeseg
.bytes
, &xu
->code_locals
, xu
);
2093 /* Enter exported symbols into hash tables */
2094 verbose(1, " registering public symbols...");
2095 enter_exported_constants(&xu
->_unit_
);
2096 enter_exported_locals(&xu
->data_locals
, &xu
->_unit_
);
2097 enter_exported_locals(&xu
->code_locals
, &xu
->_unit_
);
2098 /* Put unit in hash table */
2099 hashtab_put(unit_hash
, file
, xu
);
2100 /* Increment unit index */
2105 * Registers units based on 'link' commands in script.
2106 * @param sc Linker script
2108 static void register_units(script
*sc
)
2110 /* Table of mappings for our purpose */
2111 static script_commandprocmap map
[] = {
2112 { LINK_COMMAND
, register_one_unit
},
2113 { BAD_COMMAND
, NULL
}
2117 script_walk(sc
, map
, (void *)&i
);
2120 /*--------------------------------------------------------------------------*/
2121 /* Functions for composing a binary file based on a sequential list of
2125 * Sets the output file according to 'output' script command.
2126 * @param s Linker script
2127 * @param c Command of type OUTPUT_COMMAND
2128 * @param arg Pointer to file handle
2130 static void set_output(script
*s
, script_command
*c
, void *arg
)
2134 /* Get the name of new output file */
2135 require_arg(s
, c
, "file", file
);
2136 /* Arg is pointer to file handle pointer */
2138 /* Close current file */
2142 /* Attempt to open new file */
2143 *fpp
= fopen(file
, "wb");
2145 scripterr(s
, c
, "could not open `%s' for writing", file
);
2148 verbose(1, " output goes to `%s'", file
);
2153 * Copies a file to output according to 'copy' script command.
2154 * @param s Linker script
2155 * @param c Command of type COPY_COMMAND
2156 * @param arg Pointer to file handle
2158 static void copy_to_output(script
*s
, script_command
*c
, void *arg
)
2164 /* Arg is pointer to file handle pointer */
2166 /* Make sure there is a file to write to */
2168 scripterr(s
, c
, "no output open");
2171 /* Get the name of file to copy */
2172 require_arg(s
, c
, "file", file
);
2173 /* Attempt to open the file to copy */
2174 cf
= fopen(file
, "rb");
2176 scripterr(s
, c
, "could not open `%s' for reading", file
);
2179 verbose(1, " copying `%s' to output at position %ld...", file
, ftell(*fpp
) );
2180 /* Copy it to output, byte for byte */
2181 for (k
= fgetc(cf
); !feof(cf
); k
= fgetc(cf
) ) {
2184 /* Advance offset */
2185 bank_offset
+= ftell(cf
);
2187 /* Close the copied file */
2189 /* Check if exceeded bank size */
2190 if (bank_offset
> bank_size
) {
2191 scripterr(s
, c
, "bank size (%d) exceeded by %d bytes", bank_size
, bank_offset
- bank_size
);
2198 * Starts a new bank according to 'bank' script command.
2199 * @param s Linker script
2200 * @param c Command of type BANK_COMMAND
2201 * @param arg Pointer to file handle
2203 static void start_bank(script
*s
, script_command
*c
, void *arg
)
2207 /* See if size specified */
2208 size_str
= script_get_command_arg(c
, "size");
2209 if (size_str
!= NULL
) {
2210 /* Set new bank size */
2211 bank_size
= str_to_int(size_str
);
2213 if (bank_size
<= 0) {
2214 scripterr(s
, c
, "invalid size");
2218 /* Use bank size of previous bank if there was one */
2219 /* Otherwise issue error */
2220 if (bank_size
== 0x7FFFFFFF) {
2221 scripterr(s
, c
, "no bank size set");
2224 /* See if origin specified */
2225 origin_str
= script_get_command_arg(c
, "origin");
2226 if (origin_str
!= NULL
) {
2227 /* Set new bank origin */
2228 bank_origin
= str_to_int(origin_str
);
2230 require_arg_in_range(s
, c
, "origin", bank_origin
, 0x0000, 0xFFFF);
2233 /* Use old bank origin */
2236 /* Reset bank offset and PC */
2242 * Writes unit according to 'link' script command.
2243 * @param s Linker script
2244 * @param c Command of type LINK_COMMAND
2245 * @param arg Pointer to file handle
2247 static void write_unit(script
*s
, script_command
*c
, void *arg
)
2252 /* Arg is pointer to file handle pointer */
2254 /* Make sure there is a file to write to */
2256 scripterr(s
, c
, "no output open");
2259 /* Get the name of the unit */
2260 require_arg(s
, c
, "file", file
);
2262 xu
= (xunit
*)hashtab_get(unit_hash
, file
);
2264 verbose(1, " appending unit `%s' to output at position %ld...", file
, ftell(*fpp
));
2265 write_as_binary(*fpp
, xu
);
2266 /* Advance offset */
2267 bank_offset
+= xu
->code_size
;
2268 /* Check if exceeded bank size */
2269 if (bank_offset
> bank_size
) {
2270 scripterr(s
, c
, "bank size (%d) exceeded by %d bytes", bank_size
, bank_offset
- bank_size
);
2276 * Pads output file according to 'pad' script command.
2277 * @param s Linker script
2278 * @param c Command of type PAD_COMMAND
2279 * @param arg Pointer to file handle
2281 static void write_pad(script
*s
, script_command
*c
, void *arg
)
2291 /* Arg is pointer to file handle pointer */
2293 /* Make sure there is a file to write to */
2295 scripterr(s
, c
, "no output open");
2298 if ((offset_str
= script_get_command_arg(c
, "offset")) != NULL
) {
2299 offset
= str_to_int(offset_str
);
2300 /* Calculate number of zeroes to write */
2301 count
= offset
- bank_offset
;
2303 else if ((origin_str
= script_get_command_arg(c
, "origin")) != NULL
) {
2304 origin
= str_to_int(origin_str
);
2305 /* Calculate number of zeroes to write */
2306 count
= origin
- pc
;
2308 else if ((size_str
= script_get_command_arg(c
, "size")) != NULL
) {
2309 count
= str_to_int(size_str
);
2312 scripterr(s
, c
, "missing argument");
2317 scripterr(s
, c
, "cannot pad backwards");
2320 else if (count
> 0) {
2321 verbose(1, " padding %d bytes...", count
);
2324 for (i
=0; i
<count
; i
++) {
2327 /* Advance offset */
2328 bank_offset
+= count
;
2330 /* Check if exceeded bank size */
2331 if (bank_offset
> bank_size
) {
2332 scripterr(s
, c
, "bank size (%d) exceeded by %d bytes", bank_size
, bank_offset
- bank_size
);
2338 * Pads to end of bank in file if bank size not reached.
2339 * @param s Linker script
2340 * @param c Command of type BANK_COMMAND
2341 * @param fp File handle
2343 static void maybe_pad_bank(script
*s
, script_command
*c
, FILE *fp
)
2346 if ( (bank_size
!= 0x7FFFFFFF) && (bank_offset
< bank_size
) ) {
2347 /* Make sure there is a file to write to */
2349 scripterr(s
, c
, "no output open");
2352 /* Pad until bank size */
2353 for (i
=bank_offset
; i
<bank_size
; i
++) {
2361 * Finishes old bank in output and starts new bank.
2362 * @param s Linker script
2363 * @param c Command of type BANK_COMMAND
2364 * @param arg Pointer to file handle
2366 static void write_bank(script
*s
, script_command
*c
, void *arg
)
2369 /* Arg is pointer to file handle pointer */
2371 /* Pad bank if necessary */
2372 maybe_pad_bank(s
, c
, *fpp
);
2373 /* Start new bank */
2374 start_bank(s
, c
, arg
);
2378 * Generates the final binary output from the linker.
2379 * @param sc Linker script
2381 static void generate_output(script
*sc
)
2384 /* Table of mappings for our purpose */
2385 static script_commandprocmap map
[] = {
2386 { OUTPUT_COMMAND
, set_output
},
2387 { COPY_COMMAND
, copy_to_output
},
2388 { BANK_COMMAND
, write_bank
},
2389 { LINK_COMMAND
, write_unit
},
2390 { PAD_COMMAND
, write_pad
},
2391 { BAD_COMMAND
, NULL
}
2394 bank_size
= 0x7FFFFFFF;
2400 script_walk(sc
, map
, (void *)&fp
);
2401 /* Pad last bank if necessary */
2402 maybe_pad_bank(sc
, sc
->first_command
, fp
);
2405 /*--------------------------------------------------------------------------*/
2408 * Increases bank offset and PC according to size of the file specified by
2409 * 'copy' script command.
2410 * @param s Linker script
2411 * @param c Command of type COPY_COMMAND
2412 * @param arg Not used
2414 static void inc_offset_copy(script
*s
, script_command
*c
, void *arg
)
2418 /* Get the name of the file */
2419 require_arg(s
, c
, "file", file
);
2421 fp
= fopen(file
, "rb");
2423 scripterr(s
, c
, "could not open `%s' for reading", file
);
2427 fseek(fp
, 0, SEEK_END
);
2428 /* Advance offset */
2429 bank_offset
+= ftell(fp
);
2431 /* Close the file */
2433 /* Check if exceeded bank size */
2434 if (bank_offset
> bank_size
) {
2435 scripterr(s
, c
, "bank size (%d) exceeded by %d bytes", bank_size
, bank_offset
- bank_size
);
2441 * Sets the origin of a unit and relocates its code to this location.
2442 * @param s Linker script
2443 * @param c Command of type LINK_COMMAND
2444 * @param arg Not used
2446 static void set_unit_origin(script
*s
, script_command
*c
, void *arg
)
2452 /* Get the unit filename */
2453 require_arg(s
, c
, "file", file
);
2455 xu
= (xunit
*)hashtab_get(unit_hash
, file
);
2456 /* Check if origin specified */
2457 origin_str
= script_get_command_arg(c
, "origin");
2458 if (origin_str
!= NULL
) {
2459 origin
= str_to_int(origin_str
);
2460 require_arg_in_range(s
, c
, "origin", origin
, 0x0000, 0xFFFF);
2461 xu
->code_origin
= origin
;
2465 /* No origin specified. Set to PC. */
2466 xu
->code_origin
= pc
;
2468 xu
->bank_id
= bank_id
;
2469 /* Now we can calculate the physical code addresses of the unit. */
2470 calc_code_addresses(xu
);
2471 /* Print info if verbose mode */
2472 verbose(1, " unit `%s' relocated to %.4X", xu
->_unit_
.name
, xu
->code_origin
);
2473 /* Increase bank offset */
2474 bank_offset
+= xu
->code_size
;
2478 * Increases bank offset and PC according to 'pad' script command.
2479 * @param s Linker script
2480 * @param c Command of type PAD_COMMAND
2481 * @param arg Not used
2483 static void inc_offset_pad(script
*s
, script_command
*c
, void *arg
)
2491 if ((offset_str
= script_get_command_arg(c
, "offset")) != NULL
) {
2492 offset
= str_to_int(offset_str
);
2493 /* Calculate number of zeroes to write */
2494 count
= offset
- bank_offset
;
2496 else if ((origin_str
= script_get_command_arg(c
, "origin")) != NULL
) {
2497 origin
= str_to_int(origin_str
);
2498 /* Calculate number of zeroes to write */
2499 count
= origin
- pc
;
2501 else if ((size_str
= script_get_command_arg(c
, "size")) != NULL
) {
2502 count
= str_to_int(size_str
);
2506 scripterr(s
, c
, "missing argument");
2511 scripterr(s
, c
, "cannot pad %d bytes backwards", -count
);
2514 /* Advance offset */
2515 bank_offset
+= count
;
2517 /* Check if exceeded bank size */
2518 if (bank_offset
> bank_size
) {
2519 scripterr(s
, c
, "bank size (%d) exceeded by %d bytes", bank_size
, bank_offset
- bank_size
);
2524 * Relocates code of all units according to script commands and/or their position
2525 * in the final binary.
2526 * @param sc Linker script
2528 static void relocate_units(script
*sc
)
2530 /* Table of mappings for our purpose */
2531 static script_commandprocmap map
[] = {
2532 { COPY_COMMAND
, inc_offset_copy
},
2533 { BANK_COMMAND
, start_bank
},
2534 { LINK_COMMAND
, set_unit_origin
},
2535 { PAD_COMMAND
, inc_offset_pad
},
2536 { BAD_COMMAND
, NULL
}
2539 bank_size
= 0x7FFFFFFF;
2545 script_walk(sc
, map
, NULL
);
2551 static void maybe_print_ram_statistics()
2555 if (total_ram
> 0) {
2557 used
= total_ram
- left
;
2558 verbose(1, " total RAM: %d bytes", total_ram
);
2559 verbose(1, " RAM used: %d bytes (%d%%)", used
, (int)(((float)used
/ (float)total_ram
)*100.0f
) );
2560 verbose(1, " RAM left: %d bytes (%d%%)", left
, (int)(((float)left
/ (float)total_ram
)*100.0f
) );
2564 /*--------------------------------------------------------------------------*/
2567 * Program entrypoint.
2569 int main(int argc
, char **argv
)
2574 /* Parse our arguments. */
2575 parse_arguments(argc
, argv
);
2578 /* Reset error and warning count */
2582 /* Parse the linker script */
2583 verbose(1, "parsing linker script...");
2584 if (script_parse(program_args
.input_file
, &sc
) == 0) {
2585 /* Something bad happened when parsing script, halt */
2589 /* Process all ram commands */
2590 verbose(1, "registering RAM blocks...");
2591 register_ram_blocks(&sc
);
2593 /* Create hash tables to hold symbols */
2594 constant_hash
= hashtab_create(23, HASHTAB_STRKEYHSH
, HASHTAB_STRKEYCMP
);
2595 label_hash
= hashtab_create(23, HASHTAB_STRKEYHSH
, HASHTAB_STRKEYCMP
);
2596 unit_hash
= hashtab_create(11, HASHTAB_STRKEYHSH
, HASHTAB_STRKEYCMP
);
2598 /* Count units. One unit per link command. */
2599 unit_count
= script_count_command_type(&sc
, LINK_COMMAND
);
2600 /* Allocate array of xunits */
2601 if (unit_count
> 0) {
2602 units
= (xunit
*)malloc( sizeof(xunit
) * unit_count
);
2607 /* Process link commands */
2608 verbose(1, "loading units...");
2609 register_units(&sc
);
2610 /* Make sure all units were loaded */
2611 if (err_count
!= 0) {
2616 /* Only continue with processing if no unresolved symbols */
2617 if (err_count
== 0) {
2618 /* Calculate 0-relative addresses of data labels */
2619 verbose(1, "calculating data addresses...");
2620 for (i
=0; i
<unit_count
; i
++) {
2621 calc_data_addresses(&units
[i
]);
2624 /* TODO: Count references: go through all instructions, find EXTRN and LOCAL operands in expressions */
2625 /* TODO: Find modes of access for each DATA label (i.e. label MUST be allocated in zero page) */
2627 /* Map all data labels to 6502 RAM locations */
2628 verbose(1, "mapping data to RAM...");
2630 maybe_print_ram_statistics();
2632 /* Only continue with processing if all data labels were mapped */
2633 if (err_count
== 0) {
2634 verbose(1, "relocating code...");
2636 relocate_units(&sc
);
2638 relocate_units(&sc
);
2640 /* Only continue with processing if all code labels were mapped */
2641 if (err_count
== 0) {
2642 verbose(1, "generating output...");
2643 generate_output(&sc
);
2649 verbose(1, "cleaning up...");
2651 /* Finalize units */
2652 for (i
=0; i
<unit_count
; i
++) {
2653 if (units
[i
].loaded
) {
2654 finalize_local_array( &units
[i
].data_locals
);
2655 finalize_local_array( &units
[i
].code_locals
);
2656 unit_finalize( &units
[i
]._unit_
);
2659 /* Finalize hash tables */
2660 hashtab_finalize(label_hash
);
2661 hashtab_finalize(constant_hash
);
2662 hashtab_finalize(unit_hash
);
2663 /* Finalize RAM blocks */
2664 finalize_ram_blocks();
2665 /* Finalize the script */
2666 script_finalize(&sc
);
2669 return (err_count
== 0) ? 0 : 1;