* © 2018 Aaron Taylor <ataylor at subgeniuskitty dot com>
* See LICENSE.txt file for copyright and license details.
#include "nedasm_structures.h"
#include "nedasm_parser.h"
#include "nedasm_codegen.h"
print_usage(char ** argv
)
printf( "NED Assembler v%d (www.subgeniuskitty.com)\n"
"Usage: %s [option] ...\n"
" -h Help (prints this message)\n"
" -i <file> Specify file name of assembly code input.\n"
" -o <file> Specify file name for assembled output.\n"
enforce_word_boundary(struct instruction
* instructions
)
uint8_t syllable_counter
= 0;
struct instruction
* tmp_instructions
= instructions
;
tmp_instructions
= seek_instruction_list_start(tmp_instructions
);
while (tmp_instructions
!= NULL
) {
if (tmp_instructions
->syllable
== WORD
) {
if (syllable_counter
) insert_NOP_structs_before(tmp_instructions
, (5-syllable_counter
));
} else if (tmp_instructions
->syllable
== LABEL
) {
struct instruction
* temp
= tmp_instructions
;
while (temp
->syllable
== LABEL
) temp
= temp
->prev
;
if (syllable_counter
) insert_NOP_structs_after(temp
, (5-syllable_counter
));
} else if (tmp_instructions
->syllable
!= WORD
) {
syllable_counter
= (syllable_counter
+ 1) % 5;
tmp_instructions
= tmp_instructions
->next
;
if (syllable_counter
!= 0) {
instructions
= seek_instruction_list_end(instructions
);
insert_NOP_structs_after(instructions
, (5-syllable_counter
));
assign_addresses(struct instruction
* instructions
)
instructions
= seek_instruction_list_start(instructions
);
uint8_t increment
= 4; /* Bytes per word */
while (instructions
!= NULL
) {
if (instructions
->syllable
== LABEL
) {
instructions
= instructions
->next
;
if (instructions
->syllable
== WORD
) {
instructions
->address
= MEM_BEGIN
+ offset
;
instructions
= instructions
->next
;
for (int i
=0; i
<5; i
++) {
instructions
->address
= MEM_BEGIN
+ offset
;
instructions
= instructions
->next
;
resolve_labels(struct instruction
* instructions
)
instructions
= seek_instruction_list_start(instructions
);
while (instructions
!= NULL
) {
if (instructions
->syllable
== WORD
&& instructions
->target
!= NULL
) {
struct instruction
* temp
= seek_instruction_list_start(instructions
);
if (temp
->syllable
== LABEL
) {
if (strncmp(instructions
->target
, temp
->label
, MAX_LABEL_LEN
) == 0) {
while ((temp
->syllable
== LABEL
) && (temp
->next
!= NULL
)) {
if (temp
->syllable
!= LABEL
) {
instructions
->data
= temp
->address
;
if (instructions
->data
== 0) {
fprintf(stderr
,"ERROR: Failed to resolve label %s on line %u.\n",
instructions
->target
, instructions
->linenum
);
instructions
= instructions
->next
;
prune_label_structs(struct instruction
* instructions
)
instructions
= seek_instruction_list_start(instructions
);
while (instructions
!= NULL
) {
if (instructions
->syllable
== LABEL
) {
instructions
= remove_instruction_struct(instructions
);
instructions
= instructions
->next
;
catch_double_label_declarations(struct instruction
* instructions
)
instructions
= seek_instruction_list_start(instructions
);
while (instructions
!= NULL
) {
if (instructions
->syllable
== LABEL
) {
struct instruction
* tmp_instructions
= instructions
->next
;
while (tmp_instructions
!= NULL
) {
if (tmp_instructions
->syllable
== LABEL
) {
if (strncmp(instructions
->label
,
tmp_instructions
->label
, MAX_LABEL_LEN
) == 0
"ERROR: Multiple declarations of label %s on lines %d and %d.\n",
instructions
->label
, instructions
->linenum
,
tmp_instructions
->linenum
tmp_instructions
= tmp_instructions
->next
;
instructions
= instructions
->next
;
main(int argc
, char ** argv
)
* Process command line arguments
while ((c
= getopt(argc
,argv
,"i:o:h")) != -1) {
if ((input
= fopen(optarg
, "r")) == NULL
) {
fprintf(stderr
, "ERROR: %s: %s\n", optarg
, strerror(errno
));
/* TODO: Don't create the output file until we know the input was valid. */
if ((output
= fopen(optarg
, "wx")) == NULL
) {
fprintf(stderr
, "ERROR: %s: %s\n", optarg
, strerror(errno
));
if (input
== NULL
|| output
== NULL
) {
fprintf(stderr
, "ERROR: Must specify input and output files.\n");
* Data structure for intermediate representation.
struct instruction
* instructions
= create_instruction_struct();
instructions
->syllable
= NOP
;
* Parse input file and generate intermediate representation.
parse_assembly(&instructions
, input
);
* Make passes over the intermediate representation to enforce architecture
* rules and prepare for code generation.
catch_double_label_declarations(instructions
);
enforce_word_boundary(instructions
);
assign_addresses(instructions
);
resolve_labels(instructions
);
generate_code(instructions
, output
);