* © 2018 Aaron Taylor <ataylor at subgeniuskitty dot com>
* See LICENSE.txt file for copyright and license details.
#include "nedasm_structures.h"
write_word_to_file(uint32_t * word
, FILE * file
)
fwrite(word
, 4, 1, file
);
pad_word_boundary(uint8_t * syllable_count
, uint32_t * word
, FILE * output
)
if (*syllable_count
> 0) {
while (*syllable_count
<= 4) {
*word
|= 0b000001 << 6 * (4 - (*syllable_count
)++);
write_word_to_file(word
, output
);
generate_code_WORD(struct instruction
* instructions
, FILE * output
)
/* Set the instruction format to Type A. */
uint32_t temp_word
= 0b10000000000000000000000000000000;
/* Since x in WORD_x will be shifted left by one position, check for validity. */
if (instructions
->data
% 2 != 0) {
fprintf(stderr
, "ERROR: Unable to use odd value with WORD on line %d.\n",
if (instructions
->data
> 0b01111111111111111111111111111111) {
fprintf(stderr
, "ERROR: Value too large for WORD on line %d.\n",
/* Set the data portion of the instruction. */
temp_word
|= instructions
->data
>> 1;
write_word_to_file(&temp_word
, output
);
generate_code_IM(struct instruction
* instructions
, FILE * output
,
uint8_t * syllable_count
, uint32_t * temp_word
)
uint8_t temp_syllable
= 0b00100000;
if (instructions
->data
> 0b11111) {
fprintf(stderr
, "ERROR: Value too large for IM on line %d.\n",
temp_syllable
|= instructions
->data
;
*temp_word
|= temp_syllable
<< 6 * (4 - *syllable_count
);
generate_code_LDSP(struct instruction
* instructions
, FILE * output
,
uint8_t * syllable_count
, uint32_t * temp_word
)
uint8_t temp_syllable
= 0b00011000;
if (instructions
->data
> 0b111) {
fprintf(stderr
, "ERROR: Value too large for LDSP on line %d.\n",
temp_syllable
|= instructions
->data
;
*temp_word
|= temp_syllable
<< 6 * (4 - *syllable_count
);
generate_code_STSP(struct instruction
* instructions
, FILE * output
,
uint8_t * syllable_count
, uint32_t * temp_word
)
uint8_t temp_syllable
= 0b00010000;
if (instructions
->data
> 0b111) {
fprintf(stderr
, "ERROR: Value too large for STSP on line %d.\n",
temp_syllable
|= instructions
->data
;
*temp_word
|= temp_syllable
<< 6 * (4 - *syllable_count
);
generate_code(struct instruction
* instructions
, FILE * output
)
uint8_t syllable_count
= 0;
instructions
= seek_instruction_list_start(instructions
);
while (instructions
!= NULL
) {
/* If starting a new word, zero the word, setting it to Type C by default. */
if (syllable_count
== 0) temp_word
= 0b00000000000000000000000000000000;
switch (instructions
->syllable
) {
/* Must pad partial word w/NOPs & write to disk before starting new WORD. */
pad_word_boundary(&syllable_count
, &temp_word
, output
);
generate_code_WORD(instructions
, output
);
generate_code_IM(instructions
, output
, &syllable_count
, &temp_word
);
generate_code_LDSP(instructions
, output
, &syllable_count
, &temp_word
);
generate_code_STSP(instructions
, output
, &syllable_count
, &temp_word
);
case MVSTCK
: temp_word
|= 0b001111 << 6 * (4 - syllable_count
); break;
case ADD
: temp_word
|= 0b001100 << 6 * (4 - syllable_count
); break;
case XOR
: temp_word
|= 0b001011 << 6 * (4 - syllable_count
); break;
case NOT
: temp_word
|= 0b001010 << 6 * (4 - syllable_count
); break;
case OR
: temp_word
|= 0b001001 << 6 * (4 - syllable_count
); break;
case AND
: temp_word
|= 0b001000 << 6 * (4 - syllable_count
); break;
case BRZ
: temp_word
|= 0b000111 << 6 * (4 - syllable_count
); break;
case TEST
: temp_word
|= 0b000110 << 6 * (4 - syllable_count
); break;
case CMPSWP
: temp_word
|= 0b000101 << 6 * (4 - syllable_count
); break;
case SHIFT
: temp_word
|= 0b000100 << 6 * (4 - syllable_count
); break;
case STORE
: temp_word
|= 0b000011 << 6 * (4 - syllable_count
); break;
case LOAD
: temp_word
|= 0b000010 << 6 * (4 - syllable_count
); break;
case NOP
: temp_word
|= 0b000001 << 6 * (4 - syllable_count
); break;
case HALT
: temp_word
|= 0b000000 << 6 * (4 - syllable_count
); break;
case SWAP
: temp_word
|= 0b001101 << 6 * (4 - syllable_count
); break;
case JMP
: temp_word
|= 0b001110 << 6 * (4 - syllable_count
); break;
fprintf(stderr
, "ERROR: Unassigned syllable on line %u.\n", instructions
->linenum
);
if (syllable_count
== 4) write_word_to_file(&temp_word
, output
);
if (instructions
->syllable
!= WORD
) syllable_count
= (syllable_count
+ 1) % 5;
instructions
= instructions
->next
;
/* If necessary, pad incomplete word with NOPs. */
pad_word_boundary(&syllable_count
, &temp_word
, output
);