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.
114 #define SAFE_FREE(m) if ((m) != NULL) { free(m); m = NULL; }
117 * Parses a string to an integer.
121 static int str_to_int(char *s
)
124 return strtol(&s
[1], NULL
, 16);
126 else if (s
[0] == '%') {
127 return strtol(&s
[1], NULL
, 2);
129 return strtol(s
, NULL
, 0);
132 /*--------------------------------------------------------------------------*/
133 /* Argument parsing stuff. */
135 static char program_version
[] = "xlnk 1.5.0";
137 struct tag_arguments
{
143 typedef struct tag_arguments arguments
;
145 /* Argument variables set by arg parser. */
146 static arguments program_args
;
148 /* Long options for getopt_long(). */
149 static struct option long_options
[] = {
150 { "quiet", no_argument
, 0, 'q' },
151 { "silent", no_argument
, 0, 's' },
152 { "verbose", no_argument
, 0, 'v' },
153 { "help", no_argument
, 0, 0 },
154 { "usage", no_argument
, 0, 0 },
155 { "version", no_argument
, 0, 'V' },
159 /* Prints usage message and exits. */
163 Usage: xlnk [-qsvV] [--quiet] [--silent] [--verbose] [--help] [--usage]\n\
169 /* Prints help message and exits. */
173 Usage: xlnk [OPTION...] FILE\n\
174 The XORcyst Linker -- it creates quite a stir\n\
176 -q, -s, --quiet, --silent Don't produce any output\n\
177 -v, --verbose Produce verbose output\n\
178 --help Give this help list\n\
179 --usage Give a short usage message\n\
180 -V, --version Print program version\n\
182 Report bugs to <dev@null>.\n\
187 /* Prints version and exits. */
188 static void version()
190 printf("%s\n", program_version
);
194 /* Parses program arguments. */
196 parse_arguments (int argc
, char **argv
)
199 /* getopt_long stores the option index here. */
202 /* Set default values. */
203 program_args
.silent
= 0;
204 program_args
.verbose
= 0;
205 program_args
.input_file
= NULL
;
208 while ((key
= getopt_long(argc
, argv
, "qsvV", long_options
, &index
)) != -1) {
211 program_args
.silent
= 1;
215 program_args
.verbose
= 1;
219 /* Use index to differentiate between options */
220 if (strcmp(long_options
[index
].name
, "usage") == 0) {
223 else if (strcmp(long_options
[index
].name
, "help") == 0) {
233 /* Error message has been printed by getopt_long */
238 /* Forgot to handle a short option, most likely */
244 /* Must be one additional argument, which is the input file. */
245 if (argc
-1 != optind
) {
246 printf("Usage: xlnk [OPTION...] FILE\nTry `xlnk --help' or `xlnk --usage' for more information.\n");
250 program_args
.input_file
= argv
[optind
];
254 /*--------------------------------------------------------------------------*/
255 /* Data structures. */
257 /* Describes a local label in the unit. */
260 char *name
; /* NULL if not exported */
261 int resolved
; /* 0 initially, set to 1 when phys_addr has been assigned */
266 struct tag_xunit
*owner
;
267 unsigned short align
;
271 typedef struct tag_local local
;
273 /* Describes an array of local labels. */
274 struct tag_local_array
280 typedef struct tag_local_array local_array
;
283 * eXtended unit, has extra info built from basic unit ++
287 unit _unit_
; /* NB!!! "Superclass", must be first field for casting to work */
288 local_array data_locals
;
289 local_array code_locals
;
297 typedef struct tag_xunit xunit
;
300 * Describes a 6502 RAM block available for allocation.
302 struct tag_avail_block
304 int start
; /* Start address in 6502 space */
305 int end
; /* End address in 6502 space */
306 struct tag_avail_block
*next
;
309 typedef struct tag_avail_block avail_block
;
312 struct tag_calc_address_args
318 typedef struct tag_calc_address_args calc_address_args
;
321 struct tag_write_binary_args
327 typedef struct tag_write_binary_args write_binary_args
;
329 /*--------------------------------------------------------------------------*/
331 /** Array containing the units to link. */
333 /* Number of units in above array. */
334 static int unit_count
;
336 /** Holds the current memory address. */
339 /** Hash tables used to lookup symbols. */
340 static hashtab
*label_hash
;
341 static hashtab
*constant_hash
;
342 static hashtab
*unit_hash
;
344 /** Number of errors and warnings during linking */
345 static int err_count
;
346 static int warn_count
;
350 /* Head of the list of available 6502 RAM blocks (for data allocation). */
351 static avail_block
*first_block
= NULL
;
353 static int total_ram
= 0;
356 static int bank_offset
;
357 static int bank_size
;
358 static int bank_origin
;
362 static unsigned char *unit_file
= NULL
; /* length byte followed by chars */
363 static int unit_line
= -1;
365 /*--------------------------------------------------------------------------*/
368 * If the object file contains FILE and LINE bytecodes (assembled with
369 * --debug switch), unit_file and unit_line will contain the current
370 * source location. In that case, this function prints the location.
372 static void maybe_print_location()
376 if (unit_file
!= NULL
) {
377 /* Print source location */
378 len
= unit_file
[0] + 1;
379 str
= (char *)malloc(len
+ 1);
380 strncpy(str
, (char *)&unit_file
[1], len
);
382 fprintf(stderr
, "%s:%d: ", str
, unit_line
);
388 * If the object doesn't contain FILE and LINE bytecodes,
389 * unit_file will be <code>NULL</code>. In that case, this
390 * function prints a tip about reassembling with --debug switch.
392 static void maybe_print_debug_tip()
394 if (unit_file
== NULL
) {
395 fprintf(stderr
, "\treassemble with --debug switch to obtain source location\n");
401 * @param fmt format string for printf
403 static void err(char *fmt
, ...)
408 /* Print error message */
409 fprintf(stderr
, "error: ");
410 maybe_print_location();
411 vfprintf(stderr
, fmt
, ap
);
412 fprintf(stderr
, "\n");
413 maybe_print_debug_tip();
414 /* Increase total error count */
422 * @param fmt format string for printf
424 static void warn(char *fmt
, ...)
429 /* Print warning message */
430 fprintf(stderr
, "warning: ");
431 maybe_print_location();
432 vfprintf(stderr
, fmt
, ap
);
433 fprintf(stderr
, "\n");
434 maybe_print_debug_tip();
435 /* Increase total warning count */
442 * Prints a message if --verbose switch was given.
443 * @param fmt format string for printf
445 static void verbose(char *fmt
, ...)
449 if (!suppress
&& program_args
.verbose
) {
450 vfprintf(stdout
, fmt
, ap
);
451 fprintf(stdout
, "\n");
456 /*--------------------------------------------------------------------------*/
457 /* Functions to manage 6502 RAM blocks. */
458 /* The RAM allocator maintains a list of these blocks that are used to
459 map the contents of the units' data segments to memory.
463 * Calculates number of bytes of 6502 RAM left for allocation.
465 static int ram_left()
469 for (sum
= 0, b
= first_block
; b
!= NULL
; b
= b
->next
) {
470 sum
+= b
->end
- b
->start
;
476 * Adds a block of 6502 memory to the list of available memory regions.
477 * When adding multiple blocks they should be added in prioritized order.
478 * @param start Start address of the block
479 * @param end End address of the block (non-inclusive!)
481 static void add_ram_block(int start
, int end
)
484 /* Allocate a block struct */
485 avail_block
*new_block
= (avail_block
*)malloc( sizeof(avail_block
) );
486 if (new_block
!= NULL
) {
488 new_block
->start
= start
;
489 new_block
->end
= end
;
490 new_block
->next
= NULL
;
492 if (first_block
== NULL
) {
494 first_block
= new_block
;
498 for (b
= first_block
; b
->next
!= NULL
; b
= b
->next
) ;
501 verbose(" added RAM block: %X-%X", new_block
->start
, new_block
->end
);
506 * Allocates a chunk of 6502 RAM to a local.
508 * @return 0 if there isn't enough RAM to satisfy the request (fail), 1 otherwise (success)
510 static int alloc_ram(local
*l
)
514 /* Try the available blocks in order. */
515 /* Use the first one that's sufficient. */
518 avail_block
*p
= NULL
;
519 for (b
= first_block
; b
!= NULL
; p
= b
, b
= b
->next
) {
520 /* Check if zero page block required */
521 if (l
->flags
& LABEL_FLAG_ZEROPAGE
) {
522 if (b
->start
>= 0x100) {
523 continue; /* This block is no good */
526 /* Calculate the # of bytes left in this block */
527 left
= b
->end
- b
->start
;
528 /* See if it's enough */
529 if (left
< l
->size
) {
530 continue; /* Not enough, sorry */
532 /* Check if alignment required */
533 if (l
->flags
& LABEL_FLAG_ALIGN
) {
534 pad
= b
->start
& ((1 << l
->align
) - 1);
536 /* This block doesn't match the alignment */
537 /* Break it into two blocks if possible */
538 pad
= (1 << l
->align
) - pad
;
539 pad
= (left
< pad
) ? left
: pad
;
541 n
= (avail_block
*)malloc(sizeof(avail_block
));
543 n
->end
= n
->start
+ pad
;
546 if (b
== first_block
) {
547 first_block
= n
; /* New head */
555 l
->phys_addr
= b
->start
;
556 /* Decrease block size by moving start address ahead */
558 /* If there's no more space left in this block, discard it */
559 if (left
== l
->size
) {
560 /* Remove from linked list */
562 /* Set successor block as new head */
563 first_block
= b
->next
;
569 /* Free associated memory */
572 /* Return with success */
575 /* Couldn't find a block large enough, return with failure */
580 * Frees up memory associated with list of RAM blocks.
582 static void finalize_ram_blocks()
586 for (b
= first_block
; b
!= NULL
; b
= t
) {
592 /*--------------------------------------------------------------------------*/
593 /* Functions to get big-endian values from byte buffer. */
595 /* Gets single byte from buffer and increments index. */
596 static unsigned char get_1(unsigned char *b
, int *i
)
600 /* Gets big-endian short from buffer and increments index. */
601 static unsigned short get_2(unsigned char *b
, int *i
)
603 unsigned short result
= get_1(b
, i
) << 8;
604 result
|= get_1(b
, i
);
607 /* Gets big-endian 24-bit integer from buffer and increments index. */
608 static unsigned int get_3(unsigned char *b
, int *i
)
610 unsigned int result
= get_2(b
, i
) << 8;
611 result
|= get_1(b
, i
);
614 /* Gets big-endian int from buffer and increments index. */
615 /*static unsigned int get_4(unsigned char *b, int *i)
617 unsigned int result = get_2(b, i) << 16;
618 result |= get_2(b, i);
622 /*--------------------------------------------------------------------------*/
625 * Calculates the storage occupied by a CMD_LABEL bytecode's arguments.
627 static int label_cmd_args_size(unsigned char *bytes
)
629 int size
= 1; /* Smallest possible: flag byte */
630 int flags
= bytes
[0];
631 if (flags
& LABEL_FLAG_EXPORT
) { size
+= bytes
[1] + 1 + 1; } /* Length byte + string */
632 if (flags
& LABEL_FLAG_ALIGN
) { size
+= 1; } /* Alignment */
633 if (flags
& LABEL_FLAG_ADDR
) { size
+= 2; } /* Address */
637 /** Signature for procedure to process a bytecode */
638 typedef void (*bytecodeproc
)(unsigned char *, void *);
641 * Walks an array of bytecodes, calling corresponding bytecode handlers
643 * @param bytes Array of bytecodes, terminated by CMD_END
644 * @param handlers Array of bytecode handlers (entries can be NULL)
645 * @param arg Argument passed to bytecode handler, can be anything
647 static void bytecode_walk(unsigned char *bytes
, bytecodeproc
*handlers
, void *arg
)
653 if (bytes
== NULL
) { return; }
657 cmd
= get_1(bytes
, &i
);
659 /* Check if debug command */
663 unit_file
= &bytes
[i
];
664 i
+= get_1(bytes
, &i
) + 1; /* Skip count and array of bytes */
666 case CMD_LINE8
: unit_line
= get_1(bytes
, &i
); break;
667 case CMD_LINE16
: unit_line
= get_2(bytes
, &i
); break;
668 case CMD_LINE24
: unit_line
= get_3(bytes
, &i
); break;
669 case CMD_LINE_INC
: unit_line
++; break;
674 /* Call bytecode handler if one is present */
675 if (handlers
[cmd
-CMD_END
] != NULL
) {
676 handlers
[cmd
-CMD_END
](&bytes
[i
-1], arg
);
678 /* Skip any bytecode arguments */
681 case CMD_BIN8
: i
+= get_1(bytes
, &i
) + 1; break; /* Skip count and array of bytes */
682 case CMD_BIN16
: i
+= get_2(bytes
, &i
) + 1; break; /* Skip count and array of bytes */
683 case CMD_LABEL
: i
+= label_cmd_args_size(&bytes
[i
]); break; /* Skip flag byte and possibly name and alignment */
684 case CMD_INSTR
: i
+= 3; break; /* Skip 6502 opcode and 16-bit expr id */
685 case CMD_DB
: i
+= 2; break; /* Skip 16-bit expr id */
686 case CMD_DW
: i
+= 2; break; /* Skip 16-bit expr id */
687 case CMD_DD
: i
+= 2; break; /* Skip 16-bit expr id */
688 case CMD_DSI8
: i
+= 1; break; /* Skip 8-bit count */
689 case CMD_DSI16
: i
+= 2; break; /* Skip 16-bit count */
690 case CMD_DSB
: i
+= 2; break; /* Skip 16-bit expr id */
694 err("invalid bytecode");
697 } while (cmd
!= CMD_END
);
700 /*--------------------------------------------------------------------------*/
701 /* Functions for expression evaluation. */
704 * Finalizes a constant.
705 * @param c Constant to finalize
707 static void finalize_constant(constant
*c
)
709 if (c
->type
== STRING_CONSTANT
) {
710 SAFE_FREE(c
->string
);
715 * Gets string representation of an operator (OP_*, see objdef.h).
717 * @return String representation of operator
719 static const char *operator_to_string(int op
)
722 case OP_PLUS
: return "+";
723 case OP_MINUS
: return "-";
724 case OP_MUL
: return "*";
725 case OP_DIV
: return "/";
726 case OP_MOD
: return "%";
727 case OP_SHL
: return "<<";
728 case OP_SHR
: return ">>";
729 case OP_AND
: return "&";
730 case OP_OR
: return "|";
731 case OP_XOR
: return "^";
732 case OP_EQ
: return "==";
733 case OP_NE
: return "!=";
734 case OP_LT
: return "<";
735 case OP_GT
: return ">";
736 case OP_LE
: return "<=";
737 case OP_GE
: return ">=";
738 case OP_NOT
: return "!";
739 case OP_NEG
: return "~";
740 case OP_LO
: return "<";
741 case OP_HI
: return ">";
742 case OP_UMINUS
: return "-";
743 case OP_BANK
: return "^";
749 * Evaluates an expression recursively.
750 * The result will either be a integer or string literal, indicating successful
751 * evaluation; or an invalid type indicating that a symbol could not be translated
752 * to a constant (in other words, it could not be resolved). In this case,
753 * result->string contains the name of the symbol which couldn't be evaluated.
754 * @param u The unit where the expression is contained
755 * @param e The expression to evaluate
756 * @param result Pointer to resulting value
758 static void eval_recursive(xunit
*u
, expression
*e
, constant
*result
)
763 constant lhs_result
, rhs_result
;
765 case OPERATOR_EXPRESSION
:
766 switch (e
->op_expr
.operator) {
767 /* Binary operators */
784 /* Evaluate both sides */
785 eval_recursive(u
, e
->op_expr
.lhs
, &lhs_result
);
786 eval_recursive(u
, e
->op_expr
.rhs
, &rhs_result
);
787 /* If either side is unresolved, then result is unresolved. */
788 if ((lhs_result
.type
== -1) || (rhs_result
.type
== -1)) {
791 /* If both sides are integer, then result is integer. */
792 else if ((lhs_result
.type
== INTEGER_CONSTANT
) &&
793 (rhs_result
.type
== INTEGER_CONSTANT
)) {
794 result
->type
= INTEGER_CONSTANT
;
795 /* Perform the proper operation to obtain result. */
796 switch (e
->op_expr
.operator) {
797 case OP_PLUS
: result
->integer
= lhs_result
.integer
+ rhs_result
.integer
; break;
798 case OP_MINUS
: result
->integer
= lhs_result
.integer
- rhs_result
.integer
; break;
799 case OP_MUL
: result
->integer
= lhs_result
.integer
* rhs_result
.integer
; break;
800 case OP_DIV
: result
->integer
= lhs_result
.integer
/ rhs_result
.integer
; break;
801 case OP_MOD
: result
->integer
= lhs_result
.integer
% rhs_result
.integer
; break;
802 case OP_SHL
: result
->integer
= lhs_result
.integer
<< rhs_result
.integer
; break;
803 case OP_SHR
: result
->integer
= lhs_result
.integer
>> rhs_result
.integer
; break;
804 case OP_AND
: result
->integer
= lhs_result
.integer
& rhs_result
.integer
; break;
805 case OP_OR
: result
->integer
= lhs_result
.integer
| rhs_result
.integer
; break;
806 case OP_XOR
: result
->integer
= lhs_result
.integer
^ rhs_result
.integer
; break;
807 case OP_EQ
: result
->integer
= lhs_result
.integer
== rhs_result
.integer
; break;
808 case OP_NE
: result
->integer
= lhs_result
.integer
!= rhs_result
.integer
; break;
809 case OP_LT
: result
->integer
= lhs_result
.integer
< rhs_result
.integer
; break;
810 case OP_GT
: result
->integer
= lhs_result
.integer
> rhs_result
.integer
; break;
811 case OP_LE
: result
->integer
= lhs_result
.integer
<= rhs_result
.integer
; break;
812 case OP_GE
: result
->integer
= lhs_result
.integer
>= rhs_result
.integer
; break;
815 /* If both sides are string... */
816 else if ((lhs_result
.type
== STRING_CONSTANT
) &&
817 (rhs_result
.type
== STRING_CONSTANT
)) {
818 switch (e
->op_expr
.operator) {
821 result
->string
= (char *)malloc(strlen(lhs_result
.string
)+strlen(rhs_result
.string
)+1);
822 if (result
->string
!= NULL
) {
823 strcpy(result
->string
, lhs_result
.string
);
824 strcat(result
->string
, rhs_result
.string
);
825 result
->type
= STRING_CONSTANT
;
829 /* String comparison: using strcmp() */
830 case OP_EQ
: result
->integer
= strcmp(lhs_result
.string
, rhs_result
.string
) == 0; break;
831 case OP_NE
: result
->integer
= strcmp(lhs_result
.string
, rhs_result
.string
) != 0; break;
832 case OP_LT
: result
->integer
= strcmp(lhs_result
.string
, rhs_result
.string
) < 0; break;
833 case OP_GT
: result
->integer
= strcmp(lhs_result
.string
, rhs_result
.string
) > 0; break;
834 case OP_LE
: result
->integer
= strcmp(lhs_result
.string
, rhs_result
.string
) <= 0; break;
835 case OP_GE
: result
->integer
= strcmp(lhs_result
.string
, rhs_result
.string
) >= 0; break;
838 /* Not defined operator for string operation... */
843 /* Error, operands are incompatible */
845 err("incompatible operands to `%s' in expression", operator_to_string(e
->op_expr
.operator) );
847 /* Discard the operands */
848 finalize_constant(&lhs_result
);
849 finalize_constant(&rhs_result
);
850 break; /* Binary operator */
852 /* Unary operators */
858 /* Evaluate the single operand */
859 eval_recursive(u
, e
->op_expr
.lhs
, &lhs_result
);
860 /* If operand is unresolved then result is unresolved. */
861 if (lhs_result
.type
== -1) {
864 /* If operand is integer then result is integer. */
865 else if (lhs_result
.type
== INTEGER_CONSTANT
) {
866 result
->type
= INTEGER_CONSTANT
;
867 /* Perform the proper operation to obtain result. */
868 switch (e
->op_expr
.operator) {
869 case OP_NOT
: result
->integer
= !lhs_result
.integer
; break;
870 case OP_NEG
: result
->integer
= ~lhs_result
.integer
; break;
871 case OP_LO
: result
->integer
= lhs_result
.integer
& 0xFF; break;
872 case OP_HI
: result
->integer
= (lhs_result
.integer
>> 8) & 0xFF; break;
873 case OP_UMINUS
: result
->integer
= -lhs_result
.integer
; break;
877 /* Error, invalid operand */
878 err("incompatible operand to `%s' in expression", operator_to_string(e
->op_expr
.operator) );
881 /* Discard the operand */
882 finalize_constant(&lhs_result
);
883 break; /* Unary operator */
886 switch (e
->op_expr
.lhs
->type
) {
887 case LOCAL_EXPRESSION
:
888 /* Simple, it must be in the same (current) bank */
889 result
->integer
= bank_id
;
890 result
->type
= INTEGER_CONSTANT
;
893 case EXTERNAL_EXPRESSION
:
894 /* Get the name of the external */
895 s
= u
->_unit_
.externals
[e
->op_expr
.lhs
->extrn_id
].name
;
897 if ((l
= (local
*)hashtab_get(label_hash
, s
)) != NULL
) {
899 result
->integer
= l
->owner
->bank_id
;
900 result
->type
= INTEGER_CONSTANT
;
902 else if ((c
= (constant
*)hashtab_get(constant_hash
, s
)) != NULL
) {
903 /* It's a constant */
904 result
->integer
= ((xunit
*)c
->unit
)->bank_id
;
905 result
->type
= INTEGER_CONSTANT
;
920 case INTEGER_EXPRESSION
:
921 /* Copy value to result */
922 result
->type
= INTEGER_CONSTANT
;
923 result
->integer
= e
->integer
;
926 case STRING_EXPRESSION
:
927 /* Copy value to result */
928 result
->string
= (char *)malloc(strlen(e
->string
) + 1);
929 if (result
->string
!= NULL
) {
930 strcpy(result
->string
, e
->string
);
931 result
->type
= STRING_CONSTANT
;
935 case LOCAL_EXPRESSION
:
936 if (e
->local_id
>= u
->data_locals
.size
) {
937 /* It's a code local */
938 l
= &u
->code_locals
.entries
[e
->local_id
- u
->data_locals
.size
];
941 /* It's a data local */
942 l
= &u
->data_locals
.entries
[e
->local_id
];
944 /* Test if it's resolved */
946 /* Copy address to result */
947 result
->type
= INTEGER_CONSTANT
;
948 result
->integer
= l
->phys_addr
;
951 /* Not resolved (yet, at least) */
956 case EXTERNAL_EXPRESSION
:
957 /* Get the name of the external */
958 s
= u
->_unit_
.externals
[e
->extrn_id
].name
;
960 if ((l
= (local
*)hashtab_get(label_hash
, s
)) != NULL
) {
962 /* Test if it's resolved */
964 /* Copy address to result */
965 result
->type
= INTEGER_CONSTANT
;
966 result
->integer
= l
->phys_addr
;
969 /* Not resolved (yet) */
973 else if ((c
= (constant
*)hashtab_get(constant_hash
, s
)) != NULL
) {
974 /* It's a constant */
975 /* Copy value to result */
977 case INTEGER_CONSTANT
:
978 result
->type
= INTEGER_CONSTANT
;
979 result
->integer
= c
->integer
;
982 case STRING_CONSTANT
:
983 result
->string
= (char *)malloc(strlen(c
->string
) + 1);
984 if (result
->string
!= NULL
) {
985 strcpy(result
->string
, c
->string
);
986 result
->type
= STRING_CONSTANT
;
994 err("unknown symbol `%s' referenced from %s", s
, u
->_unit_
.name
);
999 /* Copy current PC to result */
1000 result
->type
= INTEGER_CONSTANT
;
1001 result
->integer
= pc
;
1007 * Evaluates an expression.
1008 * @param u The unit where the expression is contained
1009 * @param exid The unique ID of the expression
1010 * @param result Where to store the result of the evaluation
1012 static void eval_expression(xunit
*u
, int exid
, constant
*result
)
1014 /* Get the expression with id exid */
1015 expression
*exp
= u
->_unit_
.expressions
[exid
];
1016 /* Evaluate recursively */
1017 eval_recursive(u
, exp
, result
);
1020 /*--------------------------------------------------------------------------*/
1021 /* Functions for incrementing PC, with error handling for wraparound. */
1024 * Increases PC by amount.
1025 * Issues error if the PC wraps around.
1027 static void inc_pc(int amount
, void *arg
)
1029 calc_address_args
*aargs
;
1030 /* Check for 16-bit overflow */
1031 if ((pc
<= 0x10000) && ((pc
+amount
) > 0x10000)) {
1032 aargs
= (calc_address_args
*)arg
;
1033 err("PC went beyond 64K when linking `%s'", aargs
->xu
->_unit_
.name
);
1040 * Increases PC by 8-bit value immediately following bytecode command.
1042 static void inc_pc_count8(unsigned char *b
, void *arg
)
1045 inc_pc( get_1(b
, &i
) + 1, arg
);
1049 * Increases PC by 16-bit value immediately following bytecode command.
1051 static void inc_pc_count16(unsigned char *b
, void *arg
)
1054 inc_pc( get_2(b
, &i
) + 1, arg
);
1058 * Increases PC by 1.
1060 static void inc_pc_1(unsigned char *b
, void *arg
)
1066 * Increases PC by 2.
1068 static void inc_pc_2(unsigned char *b
, void *arg
)
1074 * Increases PC by 4.
1076 static void inc_pc_4(unsigned char *b
, void *arg
)
1082 * Increases PC according to size of define data command.
1084 static void inc_pc_dsb(unsigned char *b
, void *arg
)
1088 calc_address_args
*args
= (calc_address_args
*)arg
;
1090 /* Get expression ID */
1091 exid
= get_2(b
, &i
);
1092 /* Evaluate expression */
1093 eval_expression(args
->xu
, exid
, &c
);
1094 /* Handle the result */
1095 if (c
.type
== INTEGER_CONSTANT
) {
1096 /* An array of bytes will be located here */
1097 /* Advance PC appropriately */
1098 inc_pc( c
.integer
, arg
);
1100 else if (c
.type
== STRING_CONSTANT
) {
1101 /* Error, doesn't make sense here */
1102 err("unexpected string operand (`%s') to storage directive", c
.string
);
1105 /* Error, unresolved */
1106 //err("unresolved symbol");
1109 finalize_constant(&c
);
1113 * Increments PC according to the length of this instruction.
1115 static void inc_pc_instr(unsigned char *b
, void *arg
)
1118 unsigned char op
, t
;
1120 calc_address_args
*args
= (calc_address_args
*)arg
;
1124 /* Get expression ID */
1125 exid
= get_2(b
, &i
);
1127 eval_expression(args
->xu
, exid
, &c
);
1128 /* Handle the result */
1129 if (c
.type
== INTEGER_CONSTANT
) {
1130 /* See if it can be reduced to ZP instruction */
1131 if ((c
.integer
< 0x100) &&
1132 ((t
= opcode_zp_equiv(op
)) != 0xFF)) {
1133 /* replace op by ZP-version */
1138 else if (c
.type
== STRING_CONSTANT
) {
1139 /* Error, string operand doesn't make sense here */
1140 err("invalid instruction operand (string)");
1143 /* Address not available yet (forward reference). */
1144 //err("unresolved symbol");
1147 inc_pc( opcode_length(op
), arg
);
1150 /*--------------------------------------------------------------------------*/
1151 /* Functions for writing pure 6502 binary from bytecodes. */
1154 * Writes an array of bytes.
1156 static void write_bin8(unsigned char *b
, void *arg
)
1160 write_binary_args
*args
= (write_binary_args
*)arg
;
1161 /* Get 8-bit count */
1163 count
= get_1(b
, &i
) + 1;
1165 fwrite(&b
[i
], 1, count
, args
->fp
);
1167 inc_pc( count
, arg
);
1171 * Writes an array of bytes.
1173 static void write_bin16(unsigned char *b
, void *arg
)
1177 write_binary_args
*args
= (write_binary_args
*)arg
;
1178 /* Get 16-bit count */
1180 count
= get_2(b
, &i
) + 1;
1182 fwrite(&b
[i
], 1, count
, args
->fp
);
1184 inc_pc( count
, arg
);
1188 * Writes an instruction.
1190 static void write_instr(unsigned char *b
, void *arg
)
1196 write_binary_args
*args
= (write_binary_args
*)arg
;
1200 /* Get expression ID */
1201 exid
= get_2(b
, &i
);
1202 /* Evaluate expression */
1203 eval_expression(args
->xu
, exid
, &c
);
1205 /* Write the opcode */
1206 fputc(op
, args
->fp
);
1208 if (opcode_length(op
) == 2) {
1209 /* Operand must fit in 1 byte */
1210 /* Check if it's a relative jump */
1220 /* Calculate difference between target and address of next instruction */
1221 c
.integer
= c
.integer
- (pc
+ 2);
1222 /* Make sure jump is in range */
1223 if ( (c
.integer
< -128) || (c
.integer
> 127) ) {
1224 err("branch out of range");
1226 /* Make it a byte value */
1230 if (c
.integer
>= 0x100) {
1231 err("instruction operand doesn't fit in 1 byte");
1235 fputc(c
.integer
, args
->fp
);
1239 /* Operand must fit in 2 bytes */
1240 if (c
.integer
>= 0x10000) {
1241 err("instruction operand doesn't fit in 2 bytes");
1244 /* Write it, low byte first */
1245 fputc(c
.integer
, args
->fp
);
1246 fputc(c
.integer
>> 8, args
->fp
);
1250 inc_pc( opcode_length(op
), arg
);
1254 * Writes a byte, word or dword.
1256 static void write_dx(unsigned char *b
, void *arg
)
1261 write_binary_args
*args
= (write_binary_args
*)arg
;
1262 /* Get expression ID */
1264 exid
= get_2(b
, &i
);
1265 /* Evaluate expression */
1266 eval_expression(args
->xu
, exid
, &c
);
1268 if (c
.type
== INTEGER_CONSTANT
) {
1269 /* Write low byte */
1270 fputc(c
.integer
, args
->fp
);
1271 /* If 2+ bytes, write high ones */
1274 if (c
.integer
> 0xFF) {
1275 warn("`.DB' operand $%X out of range; truncated", c
.integer
);
1280 fputc(c
.integer
>> 8, args
->fp
);
1281 if (c
.integer
> 0xFFFF) {
1282 warn("`.DW' operand $%X out of range; truncated", c
.integer
);
1287 fputc(c
.integer
>> 8, args
->fp
);
1288 fputc(c
.integer
>> 16, args
->fp
);
1289 fputc(c
.integer
>> 24, args
->fp
);
1294 case CMD_DB
: inc_pc( 1, arg
); break;
1295 case CMD_DW
: inc_pc( 2, arg
); break;
1296 case CMD_DD
: inc_pc( 4, arg
); break;
1299 else if (c
.type
== STRING_CONSTANT
) {
1300 /* Write sequence of characters */
1301 for (i
=0; i
<strlen(c
.string
); i
++) {
1302 /* Write low byte */
1303 fputc(c
.string
[i
], args
->fp
);
1304 /* If 2+ bytes, write high ones */
1318 case CMD_DB
: inc_pc( 1, arg
); break;
1319 case CMD_DW
: inc_pc( 2, arg
); break;
1320 case CMD_DD
: inc_pc( 4, arg
); break;
1325 finalize_constant(&c
);
1329 * Writes a series of zeroes.
1331 static void write_dsi8(unsigned char *b
, void *arg
)
1335 write_binary_args
*args
= (write_binary_args
*)arg
;
1336 /* Get 8-bit count */
1338 count
= get_1(b
, &i
) + 1;
1340 for (i
=0; i
<count
; i
++) {
1344 inc_pc( count
, arg
);
1348 * Writes a series of zeroes.
1350 static void write_dsi16(unsigned char *b
, void *arg
)
1354 write_binary_args
*args
= (write_binary_args
*)arg
;
1355 /* Get 16-bit count */
1357 count
= get_2(b
, &i
) + 1;
1359 for (i
=0; i
<count
; i
++) {
1363 inc_pc( count
, arg
);
1367 * Writes a series of zeroes.
1369 static void write_dsb(unsigned char *b
, void *arg
)
1374 write_binary_args
*args
= (write_binary_args
*)arg
;
1375 /* Get expression ID */
1377 exid
= get_2(b
, &i
);
1378 /* Evaluate expression */
1379 eval_expression(args
->xu
, exid
, &c
);
1380 if (c
.integer
< 0) {
1381 err("negative count");
1383 else if (c
.integer
> 0) {
1385 for (i
=0; i
<c
.integer
; i
++) {
1389 inc_pc( c
.integer
, arg
);
1394 * Writes a code segment as fully native 6502 code.
1395 * @param fp File handle
1396 * @param u Unit whose code to write
1398 static void write_as_binary(FILE *fp
, xunit
*u
)
1400 write_binary_args args
;
1401 /* Table of callback functions for our purpose. */
1402 bytecodeproc handlers
[] =
1405 write_bin8
, /* CMD_BIN8 */
1406 write_bin16
, /* CMD_BIN16 */
1407 NULL
, /* CMD_LABEL */
1408 write_instr
, /* CMD_INSTR */
1409 write_dx
, /* CMD_DB */
1410 write_dx
, /* CMD_DW */
1411 write_dx
, /* CMD_DD */
1412 write_dsi8
, /* CMD_DSI8 */
1413 write_dsi16
, /* CMD_DSI16 */
1414 write_dsb
/* CMD_DSB */
1420 pc
= u
->code_origin
;
1422 bytecode_walk(u
->_unit_
.codeseg
.bytes
, handlers
, (void *)&args
);
1425 #define XLNK_NO_DEBUG
1426 #ifndef XLNK_NO_DEBUG
1428 /*--------------------------------------------------------------------------*/
1429 /* Functions for debugging bytecodes. */
1432 * Gets string representation of bytecode command.
1434 * @return String representation ("CMD_*")
1436 static const char *bytecode_to_string(unsigned char cmd
)
1439 case CMD_FILE
: return "CMD_FILE";
1440 case CMD_LINE8
: return "CMD_LINE8";
1441 case CMD_LINE16
:return "CMD_LINE16";
1442 case CMD_LINE24
:return "CMD_LINE24";
1443 case CMD_LINE_INC
: return "CMD_LINE_INC";
1444 case CMD_END
: return "CMD_END";
1445 case CMD_BIN8
: return "CMD_BIN8";
1446 case CMD_BIN16
: return "CMD_BIN16";
1447 case CMD_LABEL
: return "CMD_LABEL";
1448 case CMD_INSTR
: return "CMD_INSTR";
1449 case CMD_DB
: return "CMD_DB";
1450 case CMD_DW
: return "CMD_DW";
1451 case CMD_DD
: return "CMD_DD";
1452 case CMD_DSI8
: return "CMD_DSI8";
1453 case CMD_DSI16
: return "CMD_DSI16";
1454 case CMD_DSB
: return "CMD_DSB";
1456 return "bytecode_to_string: invalid bytecode";
1461 * @param b Bytecodes
1462 * @param arg Not used
1464 static void print_it(unsigned char *b
, void *arg
)
1466 printf("%s\n", bytecode_to_string(b
[0]) );
1471 * @param bytes Bytecodes
1473 static void print_bytecodes(unsigned char *bytes
)
1475 bytecodeproc handlers
[] =
1477 print_it
,print_it
,print_it
,print_it
,print_it
,
1478 print_it
,print_it
,print_it
,print_it
,print_it
,
1479 print_it
,print_it
,print_it
1481 bytecode_walk(bytes
, handlers
, NULL
);
1488 static void print_unit(unit
*u
)
1490 print_bytecodes(u
->dataseg
.bytes
);
1491 print_bytecodes(u
->codeseg
.bytes
);
1494 #endif /* !XLNK_NO_DEBUG */
1496 /*--------------------------------------------------------------------------*/
1497 /* Functions for managing arrays of unit locals. */
1500 * Creates array of locals.
1501 * @param size Number of locals
1502 * @param la Local array
1504 static void create_local_array(int size
, local_array
*la
)
1507 /* Allocate space for entries */
1509 la
->entries
= (local
*)malloc(sizeof(local
) * size
);
1517 * Finalizes array of locals.
1519 static void finalize_local_array(local_array
*la
)
1522 /* Free entry attributes */
1523 for (i
=0; i
<la
->size
; i
++) {
1524 SAFE_FREE(la
->entries
[i
].name
);
1526 /* Free array itself */
1527 SAFE_FREE(la
->entries
);
1530 /*--------------------------------------------------------------------------*/
1531 /* Functions for counting and registering locals in a unit. */
1532 /* In bytecode expressions, locals are referred to by their index.
1533 In order to not have to go through the bytecodes every time to
1534 find a label definition, the following functions build an array
1535 of structures that can be indexed by the local ID to obtain its
1540 * Counts this local.
1542 static void count_one_local(unsigned char *b
, void *arg
)
1544 /* Argument points to the counter */
1545 int *count
= (int *)arg
;
1546 /* Increment count */
1551 * Counts the number of locals (labels) in an array of bytecodes.
1552 * @param b Bytecodes, terminated by CMD_END
1553 * @return Number of locals counted
1555 static int count_locals(unsigned char *b
)
1558 /* Table of callback functions for our purpose. */
1559 bytecodeproc handlers
[] =
1562 NULL
, /* CMD_BIN8 */
1563 NULL
, /* CMD_BIN16 */
1564 count_one_local
, /* CMD_LABEL */
1565 NULL
, /* CMD_INSTR */
1569 NULL
, /* CMD_DSI8 */
1570 NULL
, /* CMD_DSI16 */
1575 /* Count the locals now */
1576 bytecode_walk(b
, handlers
, (void *)&count
);
1577 /* Return the number of locals counted */
1581 static xunit
*reg_unit
= NULL
;
1584 * Puts this local into array of locals for current unit.
1586 static void register_one_local(unsigned char *b
, void *arg
)
1590 /* Argument points to a pointer which points to the local struct to fill in */
1591 local
**lpptr
= (local
**)arg
;
1592 local
*lptr
= *lpptr
;
1593 /* Initialize some fields */
1595 lptr
->ref_count
= 0;
1598 lptr
->owner
= reg_unit
;
1600 lptr
->flags
= get_1(b
, &i
);
1601 /* Test export flag */
1602 if (lptr
->flags
& LABEL_FLAG_EXPORT
) {
1603 /* Get the length of the name */
1604 len
= get_1(b
, &i
) + 1;
1605 /* Allocate space for name */
1606 lptr
->name
= (char *)malloc( len
+ 1 );
1607 if (lptr
->name
!= NULL
) {
1608 /* Copy name from bytecodes */
1609 memcpy(lptr
->name
, &b
[i
], len
);
1610 /* Zero-terminate string */
1611 lptr
->name
[len
] = '\0';
1615 /* Test align flag */
1616 if (lptr
->flags
& LABEL_FLAG_ALIGN
) {
1617 lptr
->align
= get_1(b
, &i
);
1619 /* Test address flag */
1620 if (lptr
->flags
& LABEL_FLAG_ADDR
) {
1621 lptr
->phys_addr
= get_2(b
, &i
);
1624 /* Point to next local in array */
1629 * Puts all locals found in the array of bytecodes into array.
1630 * @param b Bytecodes, terminated by CMD_END
1631 * @param la Pointer to array to receive locals
1632 * @param xu Owner unit
1634 static void register_locals(unsigned char *b
, local_array
*la
, xunit
*xu
)
1638 /* Table of callback functions for our purpose. */
1639 bytecodeproc handlers
[] =
1642 NULL
, /* CMD_BIN8 */
1643 NULL
, /* CMD_BIN16 */
1644 register_one_local
, /* CMD_LABEL */
1645 NULL
, /* CMD_INSTR */
1649 NULL
, /* CMD_DSI8 */
1650 NULL
, /* CMD_DSI16 */
1653 /* Create array of locals */
1654 create_local_array(count_locals(b
), la
);
1660 bytecode_walk(b
, handlers
, (void *)lpptr
);
1663 /*--------------------------------------------------------------------------*/
1664 /* Functions for entering exported symbols into proper hash table. */
1667 * Enters an exported symbol into a hash table.
1668 * @param tab Hash table to enter it into
1671 * @param u Owner unit
1673 static void enter_exported_symbol(hashtab
*tab
, void *key
, void *data
, unit
*u
)
1675 /* Make sure symbol doesn't already exist */
1676 if ((hashtab_get(label_hash
, key
) != NULL
) ||
1677 (hashtab_get(constant_hash
, key
) != NULL
) ) {
1678 /* Error, duplicate symbol */
1679 err("duplicate symbol `%s' exported from unit `%s'", (char *)key
, u
->name
);
1683 hashtab_put(tab
, key
, data
);
1688 * Enters all constants in a unit into the proper hash table.
1689 * @param u Unit whose constants to enter
1691 static void enter_exported_constants(unit
*u
)
1695 /* Go through all constants in unit */
1696 for (i
=0; i
<u
->const_count
; i
++) {
1697 c
= &u
->constants
[i
];
1698 enter_exported_symbol(constant_hash
, (void *)c
->name
, (void *)c
, u
);
1703 * Enters locals which should be globally visible into the proper hash table.
1704 * @param la Array of locals
1705 * @param u Owner unit
1707 static void enter_exported_locals(local_array
*la
, unit
*u
)
1711 /* Go through all locals */
1712 for (i
=0; i
<la
->size
; i
++) {
1713 l
= &la
->entries
[i
];
1714 /* If it has a name, it is exported */
1715 if (l
->name
!= NULL
) {
1716 enter_exported_symbol(label_hash
, (void *)l
->name
, (void *)l
, u
);
1721 /*--------------------------------------------------------------------------*/
1722 /* Functions for calculating addresses of data labels in a unit. */
1725 * Sets the virtual address of this local to current PC value.
1727 static void set_data_address(unsigned char *b
, void *arg
)
1729 calc_address_args
*args
= (calc_address_args
*)arg
;
1731 local
*l
= &args
->xu
->data_locals
.entries
[args
->index
];
1733 /* Set the virtual address */
1736 /* Increase label index */
1741 * Calculates addresses of labels in a data segment relative to 0.
1742 * Only a small set of bytecode commands are allowed in a data segment:
1743 * - label (which we want to assign a virtual address)
1744 * - storage (constant or variable)
1746 static void calc_data_addresses(xunit
*u
)
1748 calc_address_args args
;
1749 /* Table of callback functions for our purpose. */
1750 bytecodeproc handlers
[] =
1753 NULL
, /* CMD_BIN8 */
1754 NULL
, /* CMD_BIN16 */
1755 set_data_address
, /* CMD_LABEL */
1756 NULL
, /* CMD_INSTR */
1760 inc_pc_count8
, /* CMD_DSI8 */
1761 inc_pc_count16
, /* CMD_DSI16 */
1762 inc_pc_dsb
/* CMD_DSB */
1770 bytecode_walk(u
->_unit_
.dataseg
.bytes
, handlers
, (void *)&args
);
1771 /* Store the end address, which is the total size of data */
1775 /*--------------------------------------------------------------------------*/
1777 /* Constructs 32-bit sort key for local. */
1778 #define SORT_KEY(l) (unsigned long)((((l)->flags & LABEL_FLAG_ZEROPAGE) << 30) | ((l)->align << 24) | (0x10000-(l)->size))
1781 * Array is sorted from high to low value.
1783 static int label_partition(local
**a
, int p
, int r
)
1791 for (j
=p
; j
<r
; j
++) {
1792 if (SORT_KEY(a
[j
]) >= x
) {
1806 * Quicksort implementation used to sort array of pointers to locals.
1808 static void label_qsort(local
**a
, int p
, int r
)
1812 q
= label_partition(a
, p
, r
);
1813 label_qsort(a
, p
, q
-1);
1814 label_qsort(a
, q
+1, r
);
1819 * Maps all data labels to 6502 RAM locations.
1820 * This is a very important function. It takes all the data labels from all
1821 * the loaded units and attempts to assign them unique physical addresses.
1822 * The list of target RAM blocks given in the linker script is the premise.
1824 static void map_data_to_ram()
1828 local
**total_order
;
1832 /* Calculate total number of labels to map */
1834 for (i
=0; i
<unit_count
; i
++) {
1835 count
+= units
[i
].data_locals
.size
;
1837 /* Put pointers to all data labels in one big array */
1838 total_order
= (local
**)malloc( count
* sizeof(local
*) );
1839 for (i
=0, k
=0; i
<unit_count
; i
++) {
1840 la
= &units
[i
].data_locals
;
1841 for (j
=0; j
<la
->size
; j
++) {
1842 /* Use virtual addresses to calculate size from this label to next */
1843 if (j
== la
->size
-1) {
1844 size
= units
[i
].data_size
;
1847 size
= la
->entries
[j
+1].virt_addr
;
1849 la
->entries
[j
].size
= size
- la
->entries
[j
].virt_addr
;
1850 /* Put pointer in array */
1851 total_order
[k
++] = &la
->entries
[j
];
1855 label_qsort(total_order
, 0, count
-1);
1857 for (i
=0; i
<count
; i
++) {
1859 /* Try to allocate it */
1860 if (alloc_ram(l
) == 1) {
1861 /* Good, label mapped successfully */
1863 if (l
->name
!= NULL
) {
1864 verbose(" %.4X-%.4X %s", l
->phys_addr
, l
->phys_addr
+ l
->size
-1, l
->name
);
1868 /* Error, couldn't allocate */
1869 err("out of 6502 RAM while allocating unit `%s'", l
->owner
->_unit_
.name
);
1876 /*--------------------------------------------------------------------------*/
1877 /* Functions for calculating offsets of code labels in a unit. */
1880 * Sets the address of this code label to current PC.
1882 static void set_code_address(unsigned char *b
, void *arg
)
1884 calc_address_args
*args
= (calc_address_args
*)arg
;
1886 local
*l
= &args
->xu
->code_locals
.entries
[args
->index
];
1888 /* Set the physical address to current PC */
1891 if ((l
->name
!= NULL
) && program_args
.verbose
) {
1892 printf(" %.4X %s\n", l
->phys_addr
, l
->name
);
1895 /* Increase label index */
1900 * Calculates addresses of code labels in a segment.
1901 * NOTE: Only the virtual addresses (relative to 0) are calculated.
1902 * The labels then need to be relocated to obtain the physical address (see below).
1905 static void calc_code_addresses(xunit
*u
)
1907 calc_address_args args
;
1908 /* Table of callback functions for our purpose. */
1909 bytecodeproc handlers
[] =
1912 inc_pc_count8
, /* CMD_BIN8 */
1913 inc_pc_count16
, /* CMD_BIN16 */
1914 set_code_address
, /* CMD_LABEL */
1915 inc_pc_instr
, /* CMD_INSTR */
1916 inc_pc_1
, /* CMD_DB -- TODO, error if string */
1917 inc_pc_2
, /* CMD_DW */
1918 inc_pc_4
, /* CMD_DD */
1919 inc_pc_count8
, /* CMD_DSI8 */
1920 inc_pc_count16
, /* CMD_DSI16 */
1921 inc_pc_dsb
/* CMD_DSB */
1927 bytecode_walk(u
->_unit_
.codeseg
.bytes
, handlers
, (void *)&args
);
1928 /* Store the total size of code */
1929 u
->code_size
= pc
- u
->code_origin
;
1932 /*--------------------------------------------------------------------------*/
1935 * Issues a script error.
1937 static void scripterr(script
*s
, script_command
*c
, char *fmt
, ...)
1942 /* Print error message */
1943 fprintf(stderr
, "error: %s:%d: `%s': ", s
->name
, c
->line
, script_command_type_to_string(c
->type
) );
1944 vfprintf(stderr
, fmt
, ap
);
1945 fprintf(stderr
, "\n");
1949 /* Increase error count */
1953 #define require_arg(s, c, a, d) { \
1954 d = script_get_command_arg(c, a); \
1956 scripterr(s, c, "missing argument `%s'", a); \
1961 #define require_arg_in_range(s, c, a, v, l, h) { \
1962 if (((v) < (l)) || ((v) > (h))) { \
1963 scripterr(s, c, "value of argument `%s' is out of range", a); \
1968 /*--------------------------------------------------------------------------*/
1969 /* Functions for registering RAM blocks in script. */
1972 * Registers one RAM block based on 'ram' script command.
1973 * @param s Linker script
1974 * @param c Command of type RAM_COMMAND
1975 * @param arg Not used
1977 static void register_one_ram_block(script
*s
, script_command
*c
, void *arg
)
1984 require_arg(s
, c
, "start", start_str
);
1985 require_arg(s
, c
, "end", end_str
);
1986 /* Convert to integers */
1987 start
= str_to_int(start_str
);
1988 end
= str_to_int(end_str
);
1989 /* Check that they are sane */
1990 require_arg_in_range(s
, c
, "start", start
, 0x0000, 0xFFFF);
1991 require_arg_in_range(s
, c
, "end", end
, 0x0000, 0xFFFF);
1993 scripterr(s
, c
, "`end' is smaller than `start'");
1996 add_ram_block(start
, end
);
2000 * Registers RAM blocks based on 'ram' commands in a script.
2001 * @param sc Linker script
2003 static void register_ram_blocks(script
*sc
)
2005 /* Table of mappings for our purpose */
2006 static script_commandprocmap map
[] = {
2007 { RAM_COMMAND
, register_one_ram_block
},
2008 { BAD_COMMAND
, NULL
}
2011 script_walk(sc
, map
, NULL
);
2012 /* Calculate total RAM size */
2013 total_ram
= ram_left();
2016 /*--------------------------------------------------------------------------*/
2017 /* Functions for loading and initial processing of units in script. */
2020 * Registers (parses etc.) one unit based on 'link' script command.
2021 * @param s Linker script
2022 * @param c Command of type LINK_COMMAND
2023 * @param arg Pointer to unit index
2025 static void register_one_unit(script
*s
, script_command
*c
, void *arg
)
2030 /* Get unit filename */
2031 require_arg(s
, c
, "file", file
);
2032 /* arg is pointer to unit index */
2034 /* Get pointer to xunit to fill in */
2036 /* Read basic unit from file */
2037 if (unit_read(file
, &xu
->_unit_
) == 0) {
2038 /* Something bad happened when trying to read unit */
2039 scripterr(s
, c
, "failed to load unit `%s'", file
);
2044 verbose(" unit `%s' loaded", file
);
2045 /* Register locals for both segments */
2046 verbose(" registering local symbols...");
2047 register_locals(xu
->_unit_
.dataseg
.bytes
, &xu
->data_locals
, xu
);
2048 register_locals(xu
->_unit_
.codeseg
.bytes
, &xu
->code_locals
, xu
);
2049 /* Enter exported symbols into hash tables */
2050 verbose(" registering public symbols...");
2051 enter_exported_constants(&xu
->_unit_
);
2052 enter_exported_locals(&xu
->data_locals
, &xu
->_unit_
);
2053 enter_exported_locals(&xu
->code_locals
, &xu
->_unit_
);
2054 /* Put unit in hash table */
2055 hashtab_put(unit_hash
, file
, xu
);
2056 /* Increment unit index */
2061 * Registers units based on 'link' commands in script.
2062 * @param sc Linker script
2064 static void register_units(script
*sc
)
2066 /* Table of mappings for our purpose */
2067 static script_commandprocmap map
[] = {
2068 { LINK_COMMAND
, register_one_unit
},
2069 { BAD_COMMAND
, NULL
}
2073 script_walk(sc
, map
, (void *)&i
);
2076 /*--------------------------------------------------------------------------*/
2077 /* Functions for composing a binary file based on a sequential list of
2081 * Sets the output file according to 'output' script command.
2082 * @param s Linker script
2083 * @param c Command of type OUTPUT_COMMAND
2084 * @param arg Pointer to file handle
2086 static void set_output(script
*s
, script_command
*c
, void *arg
)
2090 /* Get the name of new output file */
2091 require_arg(s
, c
, "file", file
);
2092 /* Arg is pointer to file handle pointer */
2094 /* Close current file */
2098 /* Attempt to open new file */
2099 *fpp
= fopen(file
, "wb");
2101 scripterr(s
, c
, "could not open `%s' for writing", file
);
2104 verbose(" output goes to `%s'", file
);
2109 * Copies a file to output according to 'copy' script command.
2110 * @param s Linker script
2111 * @param c Command of type COPY_COMMAND
2112 * @param arg Pointer to file handle
2114 static void copy_to_output(script
*s
, script_command
*c
, void *arg
)
2120 /* Arg is pointer to file handle pointer */
2122 /* Make sure there is a file to write to */
2124 scripterr(s
, c
, "no output open");
2127 /* Get the name of file to copy */
2128 require_arg(s
, c
, "file", file
);
2129 /* Attempt to open the file to copy */
2130 cf
= fopen(file
, "rb");
2132 scripterr(s
, c
, "could not open `%s' for reading", file
);
2135 verbose(" copying `%s' to output at position %ld...", file
, ftell(*fpp
) );
2136 /* Copy it to output, byte for byte */
2137 for (k
= fgetc(cf
); !feof(cf
); k
= fgetc(cf
) ) {
2140 /* Advance offset */
2141 bank_offset
+= ftell(cf
);
2143 /* Close the copied file */
2145 /* Check if exceeded bank size */
2146 if (bank_offset
> bank_size
) {
2147 scripterr(s
, c
, "bank size (%d) exceeded by %d bytes", bank_size
, bank_offset
- bank_size
);
2154 * Starts a new bank according to 'bank' script command.
2155 * @param s Linker script
2156 * @param c Command of type BANK_COMMAND
2157 * @param arg Pointer to file handle
2159 static void start_bank(script
*s
, script_command
*c
, void *arg
)
2163 /* See if size specified */
2164 size_str
= script_get_command_arg(c
, "size");
2165 if (size_str
!= NULL
) {
2166 /* Set new bank size */
2167 bank_size
= str_to_int(size_str
);
2169 if (bank_size
<= 0) {
2170 scripterr(s
, c
, "invalid size");
2174 /* Use bank size of previous bank if there was one */
2175 /* Otherwise issue error */
2176 if (bank_size
== 0x7FFFFFFF) {
2177 scripterr(s
, c
, "no bank size set");
2180 /* See if origin specified */
2181 origin_str
= script_get_command_arg(c
, "origin");
2182 if (origin_str
!= NULL
) {
2183 /* Set new bank origin */
2184 bank_origin
= str_to_int(origin_str
);
2186 require_arg_in_range(s
, c
, "origin", bank_origin
, 0x0000, 0xFFFF);
2189 /* Use old bank origin */
2192 /* Reset bank offset and PC */
2198 * Writes unit according to 'link' script command.
2199 * @param s Linker script
2200 * @param c Command of type LINK_COMMAND
2201 * @param arg Pointer to file handle
2203 static void write_unit(script
*s
, script_command
*c
, void *arg
)
2208 /* Arg is pointer to file handle pointer */
2210 /* Make sure there is a file to write to */
2212 scripterr(s
, c
, "no output open");
2215 /* Get the name of the unit */
2216 require_arg(s
, c
, "file", file
);
2218 xu
= (xunit
*)hashtab_get(unit_hash
, file
);
2220 verbose(" appending unit `%s' to output at position %ld...", file
, ftell(*fpp
));
2221 write_as_binary(*fpp
, xu
);
2222 /* Advance offset */
2223 bank_offset
+= xu
->code_size
;
2224 /* Check if exceeded bank size */
2225 if (bank_offset
> bank_size
) {
2226 scripterr(s
, c
, "bank size (%d) exceeded by %d bytes", bank_size
, bank_offset
- bank_size
);
2232 * Pads output file according to 'pad' script command.
2233 * @param s Linker script
2234 * @param c Command of type PAD_COMMAND
2235 * @param arg Pointer to file handle
2237 static void write_pad(script
*s
, script_command
*c
, void *arg
)
2247 /* Arg is pointer to file handle pointer */
2249 /* Make sure there is a file to write to */
2251 scripterr(s
, c
, "no output open");
2254 if ((offset_str
= script_get_command_arg(c
, "offset")) != NULL
) {
2255 offset
= str_to_int(offset_str
);
2256 /* Calculate number of zeroes to write */
2257 count
= offset
- bank_offset
;
2259 else if ((origin_str
= script_get_command_arg(c
, "origin")) != NULL
) {
2260 origin
= str_to_int(origin_str
);
2261 /* Calculate number of zeroes to write */
2262 count
= origin
- pc
;
2264 else if ((size_str
= script_get_command_arg(c
, "size")) != NULL
) {
2265 count
= str_to_int(size_str
);
2268 scripterr(s
, c
, "missing argument");
2273 scripterr(s
, c
, "cannot pad backwards");
2276 else if (count
> 0) {
2277 verbose(" padding %d bytes...", count
);
2280 for (i
=0; i
<count
; i
++) {
2283 /* Advance offset */
2284 bank_offset
+= count
;
2286 /* Check if exceeded bank size */
2287 if (bank_offset
> bank_size
) {
2288 scripterr(s
, c
, "bank size (%d) exceeded by %d bytes", bank_size
, bank_offset
- bank_size
);
2294 * Pads to end of bank in file if bank size not reached.
2295 * @param s Linker script
2296 * @param c Command of type BANK_COMMAND
2297 * @param fp File handle
2299 static void maybe_pad_bank(script
*s
, script_command
*c
, FILE *fp
)
2302 if ( (bank_size
!= 0x7FFFFFFF) && (bank_offset
< bank_size
) ) {
2303 /* Make sure there is a file to write to */
2305 scripterr(s
, c
, "no output open");
2308 /* Pad until bank size */
2309 for (i
=bank_offset
; i
<bank_size
; i
++) {
2317 * Finishes old bank in output and starts new bank.
2318 * @param s Linker script
2319 * @param c Command of type BANK_COMMAND
2320 * @param arg Pointer to file handle
2322 static void write_bank(script
*s
, script_command
*c
, void *arg
)
2325 /* Arg is pointer to file handle pointer */
2327 /* Pad bank if necessary */
2328 maybe_pad_bank(s
, c
, *fpp
);
2329 /* Start new bank */
2330 start_bank(s
, c
, arg
);
2334 * Generates the final binary output from the linker.
2335 * @param sc Linker script
2337 static void generate_output(script
*sc
)
2340 /* Table of mappings for our purpose */
2341 static script_commandprocmap map
[] = {
2342 { OUTPUT_COMMAND
, set_output
},
2343 { COPY_COMMAND
, copy_to_output
},
2344 { BANK_COMMAND
, write_bank
},
2345 { LINK_COMMAND
, write_unit
},
2346 { PAD_COMMAND
, write_pad
},
2347 { BAD_COMMAND
, NULL
}
2350 bank_size
= 0x7FFFFFFF;
2356 script_walk(sc
, map
, (void *)&fp
);
2357 /* Pad last bank if necessary */
2358 maybe_pad_bank(sc
, sc
->first_command
, fp
);
2361 /*--------------------------------------------------------------------------*/
2364 * Increases bank offset and PC according to size of the file specified by
2365 * 'copy' script command.
2366 * @param s Linker script
2367 * @param c Command of type COPY_COMMAND
2368 * @param arg Not used
2370 static void inc_offset_copy(script
*s
, script_command
*c
, void *arg
)
2374 /* Get the name of the file */
2375 require_arg(s
, c
, "file", file
);
2377 fp
= fopen(file
, "rb");
2379 scripterr(s
, c
, "could not open `%s' for reading", file
);
2383 fseek(fp
, 0, SEEK_END
);
2384 /* Advance offset */
2385 bank_offset
+= ftell(fp
);
2387 /* Close the file */
2389 /* Check if exceeded bank size */
2390 if (bank_offset
> bank_size
) {
2391 scripterr(s
, c
, "bank size (%d) exceeded by %d bytes", bank_size
, bank_offset
- bank_size
);
2397 * Sets the origin of a unit and relocates its code to this location.
2398 * @param s Linker script
2399 * @param c Command of type LINK_COMMAND
2400 * @param arg Not used
2402 static void set_unit_origin(script
*s
, script_command
*c
, void *arg
)
2408 /* Get the unit filename */
2409 require_arg(s
, c
, "file", file
);
2411 xu
= (xunit
*)hashtab_get(unit_hash
, file
);
2412 /* Check if origin specified */
2413 origin_str
= script_get_command_arg(c
, "origin");
2414 if (origin_str
!= NULL
) {
2415 origin
= str_to_int(origin_str
);
2416 require_arg_in_range(s
, c
, "origin", origin
, 0x0000, 0xFFFF);
2417 xu
->code_origin
= origin
;
2421 /* No origin specified. Set to PC. */
2422 xu
->code_origin
= pc
;
2424 xu
->bank_id
= bank_id
;
2425 /* Now we can calculate the physical code addresses of the unit. */
2426 calc_code_addresses(xu
);
2427 /* Print info if verbose mode */
2428 verbose(" unit `%s' relocated to %.4X", xu
->_unit_
.name
, xu
->code_origin
);
2429 /* Increase bank offset */
2430 bank_offset
+= xu
->code_size
;
2434 * Increases bank offset and PC according to 'pad' script command.
2435 * @param s Linker script
2436 * @param c Command of type PAD_COMMAND
2437 * @param arg Not used
2439 static void inc_offset_pad(script
*s
, script_command
*c
, void *arg
)
2447 if ((offset_str
= script_get_command_arg(c
, "offset")) != NULL
) {
2448 offset
= str_to_int(offset_str
);
2449 /* Calculate number of zeroes to write */
2450 count
= offset
- bank_offset
;
2452 else if ((origin_str
= script_get_command_arg(c
, "origin")) != NULL
) {
2453 origin
= str_to_int(origin_str
);
2454 /* Calculate number of zeroes to write */
2455 count
= origin
- pc
;
2457 else if ((size_str
= script_get_command_arg(c
, "size")) != NULL
) {
2458 count
= str_to_int(size_str
);
2462 scripterr(s
, c
, "missing argument");
2467 scripterr(s
, c
, "cannot pad %d bytes backwards", -count
);
2470 /* Advance offset */
2471 bank_offset
+= count
;
2473 /* Check if exceeded bank size */
2474 if (bank_offset
> bank_size
) {
2475 scripterr(s
, c
, "bank size (%d) exceeded by %d bytes", bank_size
, bank_offset
- bank_size
);
2480 * Relocates code of all units according to script commands and/or their position
2481 * in the final binary.
2482 * @param sc Linker script
2484 static void relocate_units(script
*sc
)
2486 /* Table of mappings for our purpose */
2487 static script_commandprocmap map
[] = {
2488 { COPY_COMMAND
, inc_offset_copy
},
2489 { BANK_COMMAND
, start_bank
},
2490 { LINK_COMMAND
, set_unit_origin
},
2491 { PAD_COMMAND
, inc_offset_pad
},
2492 { BAD_COMMAND
, NULL
}
2495 bank_size
= 0x7FFFFFFF;
2501 script_walk(sc
, map
, NULL
);
2507 static void maybe_print_ram_statistics()
2511 if (total_ram
> 0) {
2513 used
= total_ram
- left
;
2514 verbose(" total RAM: %d bytes", total_ram
);
2515 verbose(" RAM used: %d bytes (%d%%)", used
, (int)(((float)used
/ (float)total_ram
)*100.0f
) );
2516 verbose(" RAM left: %d bytes (%d%%)", left
, (int)(((float)left
/ (float)total_ram
)*100.0f
) );
2520 /*--------------------------------------------------------------------------*/
2523 * Program entrypoint.
2525 int main(int argc
, char **argv
)
2530 /* Parse our arguments. */
2531 parse_arguments(argc
, argv
);
2534 /* Reset error and warning count */
2538 /* Parse the linker script */
2539 verbose("parsing linker script...");
2540 if (script_parse(program_args
.input_file
, &sc
) == 0) {
2541 /* Something bad happened when parsing script, halt */
2545 /* Process all ram commands */
2546 verbose("registering RAM blocks...");
2547 register_ram_blocks(&sc
);
2549 /* Create hash tables to hold symbols */
2550 constant_hash
= hashtab_create(23, HASHTAB_STRKEYHSH
, HASHTAB_STRKEYCMP
);
2551 label_hash
= hashtab_create(23, HASHTAB_STRKEYHSH
, HASHTAB_STRKEYCMP
);
2552 unit_hash
= hashtab_create(11, HASHTAB_STRKEYHSH
, HASHTAB_STRKEYCMP
);
2554 /* Count units. One unit per link command. */
2555 unit_count
= script_count_command_type(&sc
, LINK_COMMAND
);
2556 /* Allocate array of xunits */
2557 if (unit_count
> 0) {
2558 units
= (xunit
*)malloc( sizeof(xunit
) * unit_count
);
2563 /* Process link commands */
2564 verbose("loading units...");
2565 register_units(&sc
);
2566 /* Make sure all units were loaded */
2567 if (err_count
!= 0) {
2571 /* Only continue with processing if no unresolved symbols */
2572 if (err_count
== 0) {
2573 /* Calculate 0-relative addresses of data labels */
2574 verbose("calculating data addresses...");
2575 for (i
=0; i
<unit_count
; i
++) {
2576 calc_data_addresses(&units
[i
]);
2579 // TODO: Count references: go through all instructions, find EXTRN and LOCAL operands in expressions
2580 // TODO: Find modes of access for each DATA label (i.e. label MUST be allocated in zero page)
2582 /* Map all data labels to 6502 RAM locations */
2583 verbose("mapping data to RAM...");
2585 maybe_print_ram_statistics();
2587 /* Only continue with processing if all data labels were mapped */
2588 if (err_count
== 0) {
2589 verbose("relocating code...");
2591 relocate_units(&sc
);
2593 relocate_units(&sc
);
2595 /* Only continue with processing if all code labels were mapped */
2596 if (err_count
== 0) {
2597 verbose("generating output...");
2598 generate_output(&sc
);
2604 verbose("cleaning up...");
2606 /* Finalize units */
2607 for (i
=0; i
<unit_count
; i
++) {
2608 if (units
[i
].loaded
) {
2609 finalize_local_array( &units
[i
].data_locals
);
2610 finalize_local_array( &units
[i
].code_locals
);
2611 unit_finalize( &units
[i
]._unit_
);
2614 /* Finalize hash tables */
2615 hashtab_finalize(label_hash
);
2616 hashtab_finalize(constant_hash
);
2617 hashtab_finalize(unit_hash
);
2618 /* Finalize RAM blocks */
2619 finalize_ram_blocks();
2620 /* Finalize the script */
2621 script_finalize(&sc
);
2624 return (err_count
== 0) ? 0 : 1;