コード例 #1
0
ファイル: assem.c プロジェクト: kierenj/DCPUToolchain
void process_line(struct ast_node_line* line)
{
	struct instruction_mapping* insttype;
	struct process_parameters_results ppresults;
	struct process_parameter_results dparam;
	struct ast_node_parameter* dcurrent;
	uint32_t dchrproc;
	uint16_t i, flimit, fchar, opos;

	// Change depending on the type of line.
	switch (line->type)
	{
		case type_keyword:
			switch (line->keyword)
			{
				case BOUNDARY:
					fprintf(stderr, ".BOUNDARY");

					// Emit safety boundary of 16 NULL words.
					for (i = 0; i < 16; i += 1)
						aout_emit(aout_create_raw(0));

					break;

				case FILL:
					fprintf(stderr, ".FILL");

					// Emit N words with value X
					flimit = expr_evaluate(line->keyword_data_expr_1, &ahalt_label_resolution_not_permitted, &ahalt_expression_exit_handler);
					fchar = expr_evaluate(line->keyword_data_expr_2, &ahalt_label_resolution_not_permitted, &ahalt_expression_exit_handler);
					for (i = 0; i < flimit; i++)
						aout_emit(aout_create_raw(fchar));

					break;

				case EXTENSION:
					fprintf(stderr, ".EXTENSION %s", line->keyword_data_string);

					// Emit extension metadata.
					aout_emit(aout_create_metadata_extension(bstr2cstr(line->keyword_data_string, '0')));

					break;

				case INCBIN:
					fprintf(stderr, ".INCBIN %s", line->keyword_data_string);

					// Emit binary include metadata.
					aout_emit(aout_create_metadata_incbin(bstr2cstr(line->keyword_data_string, '0')));

					break;

				case ORIGIN:
					opos = expr_evaluate(line->keyword_data_expr_1, &ahalt_label_resolution_not_permitted, &ahalt_expression_exit_handler);
					fprintf(stderr, ".ORIGIN 0x%04X", opos);

					// Emit origin set metadata.
					aout_emit(aout_create_metadata_origin(opos));

					break;

				case EXPORT:
					fprintf(stderr, ".EXPORT %s", line->keyword_data_string);

					// Emit export metadata.
					aout_emit(aout_create_metadata_export(bstr2cstr(line->keyword_data_string, '0')));

					break;

				case IMPORT:
					fprintf(stderr, ".IMPORT %s", line->keyword_data_string);

					// Emit export metadata.
					aout_emit(aout_create_metadata_import(bstr2cstr(line->keyword_data_string, '0')));

					break;

				default:
					fprintf(stderr, "\n");
					ahalt(ERR_UNSUPPORTED_KEYWORD, NULL);
			}

			fprintf(stderr, "\n");
			break;

		case type_instruction:

			// Check to see if this is DAT.
			if (strcmp(line->instruction->instruction, "DAT") == 0)
			{
				// Handle data.
				fprintf(stderr, "EMIT DAT");

				// Process parameters as data.
				reverse_parameters(line->instruction->parameters);
				dcurrent = line->instruction->parameters->last;

				while (dcurrent != NULL)
				{
					// Process parameter normally.
					dparam = process_parameter(dcurrent);

					// Output depending on what kind of parameter it was.
					if (dparam.v_label != NULL) // If this is a label, output something that we need to replace.
						aout_emit(aout_create_expr(expr_new_label(bautofree(bfromcstr(dparam.v_label)))));
					else if (dparam.v_raw != NULL) // If the raw field is not null, get each character and output it.
					{
						fprintf(stderr, " \"%s\"", dparam.v_raw->data);

						for (dchrproc = 0; dchrproc < blength(dparam.v_raw); dchrproc++)
							aout_emit(aout_create_raw(dparam.v_raw->data[dchrproc]));
					}
					else if (dparam.v_extra_used == true) // Just a single address.
						aout_emit(aout_create_expr(dparam.v_extra));
					else // Something that isn't handled by DAT.
					{
						fprintf(stderr, "\n");
						ahalt(ERR_DAT_UNSUPPORTED_PARAMETER, NULL);
					}

					dcurrent = dcurrent->prev;
				}
			}
			else
			{
				// Handle instruction.
				insttype = get_instruction_by_name(line->instruction->instruction);

				if (insttype == NULL)
					ahalt(ERR_UNKNOWN_OPCODE, line->instruction->instruction);

				fprintf(stderr, "EMIT %s", insttype->name);

				// Process parameters normally.
				ppresults = process_parameters(line->instruction->parameters);

				// Force the parameter value to be NXT if it's a label.
				if (ppresults.a_label != NULL) ppresults.a = NXT_LIT;

				if (ppresults.b_label != NULL) ppresults.b = NXT_LIT;

				if (ppresults.a_label != NULL && ppresults.a_label_bracketed) ppresults.a = NXT;

				if (ppresults.b_label != NULL && ppresults.b_label_bracketed) ppresults.b = NXT;

				// Output the initial opcode.
				if (insttype->opcode != OP_NONBASIC)
					aout_emit(aout_create_opcode(insttype->opcode, ppresults.a, ppresults.b));
				else
					aout_emit(aout_create_opcode(insttype->opcode, insttype->nbopcode, ppresults.a));

				// If the parameter is a label or requires an extra word, output them.
				if (ppresults.b_label != NULL)
					aout_emit(aout_create_expr(expr_new_label(bautofree(bfromcstr(ppresults.b_label)))));
				else if (ppresults.b_extra_used)
					aout_emit(aout_create_expr(ppresults.b_extra));

				if (ppresults.a_label != NULL)
					aout_emit(aout_create_expr(expr_new_label(bautofree(bfromcstr(ppresults.a_label)))));
				else if (ppresults.a_extra_used)
					aout_emit(aout_create_expr(ppresults.a_extra));

			}

			fprintf(stderr, "\n");
			break;

		case type_label:
			// Handle label definition.
			fprintf(stderr, ":%s\n", line->label->name);
			aout_emit(aout_create_label(line->label->name));
			break;
	}
}
コード例 #2
0
ファイル: assem.c プロジェクト: jathd/DCPUToolchain
void process_line(struct ast_node_line* line)
{
    struct instruction_mapping* insttype;
    struct process_parameters_results ppresults;
    struct process_parameter_results dparam;
    struct ast_node_parameter* dcurrent;
    uint32_t dchrproc;
    uint16_t i, flimit, fchar, opos;
    struct aout_byte* result = NULL;
    struct dbg_sym* newsym;

    // Change depending on the type of line.
    switch (line->type)
    {
        case type_keyword:
            switch (line->keyword)
            {
                case SYMBOL:
                    printd(LEVEL_VERBOSE, ".SYMBOL %s", bstr2cstr(line->keyword_data_string, '0'));

                    // Emit debugging symbol.
                    list_append(&newsyms, dbgfmt_create_symbol(DBGFMT_SYMBOL_STRING, dbgfmt_create_symbol_string(line->keyword_data_string, DBGFMT_UNDETERMINED)));

                    break;

                case SECTION:
                    printd(LEVEL_VERBOSE, ".SECTION %s", bstr2cstr(line->keyword_data_string, '0'));

                    // Emit section metadata.
                    aout_emit(aout_create_metadata_section(bstr2cstr(line->keyword_data_string, '0')));

                    break;

                case OUTPUT:
                    printd(LEVEL_VERBOSE, ".OUTPUT %s", bstr2cstr(line->keyword_data_string, '0'));

                    // Emit output metadata.
                    aout_emit(aout_create_metadata_output(bstr2cstr(line->keyword_data_string, '0')));

                    break;

                case BOUNDARY:
                    printd(LEVEL_VERBOSE, ".BOUNDARY");

                    // Emit safety boundary of 16 NULL words.
                    for (i = 0; i < 16; i += 1)
                        aout_emit(aout_create_raw(0));

                    break;

                case FILL:
                    printd(LEVEL_VERBOSE, ".FILL");

                    if (line->keyword_data_expr_1 == NULL || line->keyword_data_expr_2 == NULL)
                    {
                        if (line->keyword_data_string != NULL)
                            dhalt(ERR_LABEL_RESOLUTION_NOT_PERMITTED, line->keyword_data_string->data);
                        else
                            dhalt(ERR_LABEL_RESOLUTION_NOT_PERMITTED, "");
                    }

                    // Emit N words with value X
                    flimit = expr_evaluate(line->keyword_data_expr_1, &dhalt_label_resolution_not_permitted, &dhalt_expression_exit_handler);
                    fchar = expr_evaluate(line->keyword_data_expr_2, &dhalt_label_resolution_not_permitted, &dhalt_expression_exit_handler);
                    for (i = 0; i < flimit; i++)
                        aout_emit(aout_create_raw(fchar));

                    break;

                case EXTENSION:
                    printd(LEVEL_VERBOSE, ".EXTENSION %s", bstr2cstr(line->keyword_data_string, '0'));

                    // Emit extension metadata.
                    aout_emit(aout_create_metadata_extension(bstr2cstr(line->keyword_data_string, '0')));

                    break;

                case INCBIN:
                    printd(LEVEL_VERBOSE, ".INCBIN %s", bstr2cstr(line->keyword_data_string, '0'));

                    // Emit binary include metadata.
                    aout_emit(aout_create_metadata_incbin(bstr2cstr(line->keyword_data_string, '0')));

                    break;

                case ORIGIN:
                    if (line->keyword_data_expr_1 == NULL)
                    {
                        if (line->keyword_data_string != NULL)
                            dhalt(ERR_LABEL_RESOLUTION_NOT_PERMITTED, line->keyword_data_string->data);
                        else
                            dhalt(ERR_LABEL_RESOLUTION_NOT_PERMITTED, "");
                    }

                    opos = expr_evaluate(line->keyword_data_expr_1, &dhalt_label_resolution_not_permitted, &dhalt_expression_exit_handler);
                    printd(LEVEL_VERBOSE, ".ORIGIN 0x%04X", opos);

                    // Emit origin set metadata.
                    aout_emit(aout_create_metadata_origin(opos));

                    break;

                case SEEK:
                    if (line->keyword_data_expr_1 == NULL)
                    {
                        if (line->keyword_data_string != NULL)
                            dhalt(ERR_LABEL_RESOLUTION_NOT_PERMITTED, line->keyword_data_string->data);
                        else
                            dhalt(ERR_LABEL_RESOLUTION_NOT_PERMITTED, "");
                    }

                    opos = expr_evaluate(line->keyword_data_expr_1, &dhalt_label_resolution_not_permitted, &dhalt_expression_exit_handler);
                    printd(LEVEL_VERBOSE, ".SEEK 0x%04X", opos);

                    // Emit seek metadata.
                    aout_emit(aout_create_metadata_seek(opos));

                    break;

                case EXPORT:
                    printd(LEVEL_VERBOSE, ".EXPORT %s", bstr2cstr(line->keyword_data_string, '0'));

                    // Emit export metadata.
                    aout_emit(aout_create_metadata_export(bstr2cstr(line->keyword_data_string, '0')));

                    break;

                case IMPORT:
                    printd(LEVEL_VERBOSE, ".IMPORT %s", bstr2cstr(line->keyword_data_string, '0'));

                    // Emit import metadata.
                    aout_emit(aout_create_metadata_import(bstr2cstr(line->keyword_data_string, '0')));

                    break;

                case IMPORT_OPTIONAL:
                    printd(LEVEL_VERBOSE, ".IMPORT OPTIONAL %s", bstr2cstr(line->keyword_data_string, '0'));

                    // Emit import metadata.
                    aout_emit(aout_create_metadata_import_optional(bstr2cstr(line->keyword_data_string, '0')));

                    break;

                case JUMP:
                    if (line->keyword_data_string == NULL)
                        printd(LEVEL_VERBOSE, ".JUMP <table>");
                    else
                        printd(LEVEL_VERBOSE, ".JUMP %s", bstr2cstr(line->keyword_data_string, '0'));

                    // Emit jump metadata.
                    if (line->keyword_data_string == NULL)
                        aout_emit(aout_create_metadata_jump(NULL));
                    else
                        aout_emit(aout_create_metadata_jump(bstr2cstr(line->keyword_data_string, '0')));

                    break;

                default:
                    printd(LEVEL_VERBOSE, "?? UNKNOWN KEYWORD\n");
                    dhalt(ERR_UNSUPPORTED_KEYWORD, NULL);
            }

            printd(LEVEL_VERBOSE, "\n");
            break;

        case type_instruction:

            // Check to see if this is DAT.
            if (strcmp(line->instruction->instruction, "DAT") == 0)
            {
                // Handle data.
                printd(LEVEL_VERBOSE, "EMIT DAT");

                // Process parameters as data.
                reverse_parameters(line->instruction->parameters);
                dcurrent = line->instruction->parameters->last;

                while (dcurrent != NULL)
                {
                    // Process parameter normally.
                    dparam = process_parameter(dcurrent);

                    // Output depending on what kind of parameter it was.
                    if (dparam.v_label != NULL) // If this is a label, output something that we need to replace.
                        aout_emit(aout_create_expr(expr_new_label(bautofree(bfromcstr(dparam.v_label)))));
                    else if (dparam.v_raw != NULL) // If the raw field is not null, get each character and output it.
                    {
                        printd(LEVEL_VERBOSE, " \"%s\"", dparam.v_raw->data);

                        for (dchrproc = 0; dchrproc < (uint32_t)blength(dparam.v_raw); dchrproc++)
                            aout_emit(aout_create_raw(dparam.v_raw->data[dchrproc]));
                    }
                    else if (dparam.v_extra_used == true) // Just a single address.
                        aout_emit(aout_create_expr(dparam.v_extra));
                    else // Something that isn't handled by DAT.
                    {
                        printd(LEVEL_VERBOSE, "\n");
                        dhalt(ERR_DAT_UNSUPPORTED_PARAMETER, NULL);
                    }

                    dcurrent = dcurrent->prev;
                }
            }
            else
            {
                // Handle instruction.
                insttype = get_instruction_by_name(line->instruction->instruction);

                if (insttype == NULL)
                    dhalt(ERR_UNKNOWN_OPCODE, line->instruction->instruction);

                printd(LEVEL_VERBOSE, "EMIT %s", insttype->name);

                // Check parameter count.
                if (line->instruction->parameters == NULL && strcmp(line->instruction->instruction, "RFI") == 0)
                {
                    // Handle RFI (which can accept no parameters).
                    result = aout_emit(aout_create_opcode(insttype->opcode, insttype->nbopcode, 0x21 /* 0 literal */));
                    printd(LEVEL_VERBOSE, "\n");
                    break;
                }
                else if (line->instruction->parameters == NULL)
                {
                    // Halt and error.
                    dhalt(ERR_INVALID_PARAMETER_COUNT, NULL);
                }

                // Process parameters normally.
                ppresults = process_parameters(line->instruction->parameters);

                // Force the parameter value to be NXT if it's a label.
                if (ppresults.a_label != NULL) ppresults.a = NXT_LIT;
                if (ppresults.b_label != NULL) ppresults.b = NXT_LIT;
                if (ppresults.a_label != NULL && ppresults.a_label_bracketed) ppresults.a = NXT;
                if (ppresults.b_label != NULL && ppresults.b_label_bracketed) ppresults.b = NXT;

                // Check for relative addressing.
                if ((insttype->opcode == OP_ADD || insttype->opcode == OP_SUB ||
                        insttype->opcode == OP_MUL || insttype->opcode == OP_DIV) && ppresults.a == PC)
                {
                    // Warn about relative addressing portability.
                    dwarn(WARN_RELATIVE_PC_ADDRESSING, NULL);
                }

                // Output the initial opcode.
                if (insttype->opcode != OP_NONBASIC)
                    result = aout_emit(aout_create_opcode(insttype->opcode, ppresults.a, ppresults.b));
                else
                    result = aout_emit(aout_create_opcode(insttype->opcode, insttype->nbopcode, ppresults.a));

                // If the parameter is a label or requires an extra word, output them.
                if (ppresults.b_label != NULL)
                    aout_emit(aout_create_expr(expr_new_label(bautofree(bfromcstr(ppresults.b_label)))));
                else if (ppresults.b_extra_used)
                    aout_emit(aout_create_expr(ppresults.b_extra));

                if (ppresults.a_label != NULL)
                    aout_emit(aout_create_expr(expr_new_label(bautofree(bfromcstr(ppresults.a_label)))));
                else if (ppresults.a_extra_used)
                    aout_emit(aout_create_expr(ppresults.a_extra));

            }

            printd(LEVEL_VERBOSE, "\n");
            break;

        case type_label:
            // Handle label definition.
            list_append(&newsyms, dbgfmt_create_symbol(DBGFMT_SYMBOL_LABEL, dbgfmt_create_symbol_label(bfromcstr(line->label->name), DBGFMT_UNDETERMINED)));
            printd(LEVEL_VERBOSE, ":%s\n", line->label->name);
            aout_emit(aout_create_label(line->label->name));
            break;

        default:
            assert(false);
    }

    // If we can associate debugging symbols with this instruction...
    if (result != NULL)
    {
        // While the new symbols list is not empty, copy those symbols
        // into the output and associate.
        while (list_size(&newsyms) > 0)
        {
            newsym = list_extract_at(&newsyms, 0);
            printd(LEVEL_DEBUG, "Debugging custom symbol: %i\n", newsym->length);
            list_append(&result->symbols, newsym);
            list_append(assem_dbg_symbols, newsym);
        }

        // If the line information is provided, output
        // debugging symbols.
        if (line != NULL && line->file != NULL)
        {
            // Output a file / line number debugging symbol here.
            newsym = dbgfmt_create_symbol(DBGFMT_SYMBOL_LINE, dbgfmt_create_symbol_line(line->file, line->line, DBGFMT_UNDETERMINED));
            list_append(&result->symbols, newsym);
            list_append(assem_dbg_symbols, newsym);

            printd(LEVEL_DEBUG, "Debugging symbol: %i %s\n", line->line, line->file->data);
        }

        // If the higher-language line information is
        // provided, output debugging symbols.
        if (line != NULL && line->ufile != NULL)
        {
            // Output a file / line number debugging symbol here.
            newsym = dbgfmt_create_symbol(DBGFMT_SYMBOL_LINE, dbgfmt_create_symbol_line(line->ufile, line->uline, DBGFMT_UNDETERMINED));
            list_append(&result->symbols, newsym);
            list_append(assem_dbg_symbols, newsym);

            printd(LEVEL_DEBUG, "High-level debugging symbol: %i %s\n", line->uline, line->ufile->data);
        }
    }
}