Exemple #1
0
static uint16_t if_define_replace(bstring define)
{
    // Search through all of the defines to find one where
    // the name matches.
    size_t i = 0;
    match_t* match;
    struct expr* tree;
    for (i = 0; i < list_size(&replace_state->handlers); i++)
    {
        match = list_get_at(&replace_state->handlers, i);
        if (biseq(match->text.ref, define))
        {
            // Found a match.
            tree = expr_parse(match->userdata);
            if (tree == NULL)
                dhalt(ERR_PP_DEFINE_NOT_EXPRESSION, ppimpl_get_location(replace_state));
            return expr_evaluate(tree, &if_define_replace, &dhalt_expression_exit_handler);
        }
    }
    dhalt(ERR_PP_DEFINE_NOT_FOUND, ppimpl_get_location(replace_state));
    return 0;
}
Exemple #2
0
static void if_handle(state_t* state, match_t* match, bool* reprocess)
{
    list_t* result = ppparam_get(state);
    struct expr* expr = NULL;
    uint16_t value;
    bstring output;
    bool stopped_at_else;

    // Ensure the parameter format is correct.
    if (list_size(result) == 1 &&
            ((parameter_t*)list_get_at(result, 0))->type == EXPRESSION)
    {
        // Get the expression.
        expr = ((parameter_t*)list_get_at(result, 0))->expr;
        replace_state = state;
        value = expr_evaluate(expr, &if_define_replace, &dhalt_expression_exit_handler);
        replace_state = NULL;
        
        if (value)
        {
            output = skip_to_endif(state, true, &stopped_at_else);
            if (stopped_at_else)
                skip_to_endif(state, false, &stopped_at_else);
        }
        else
        {
            bassigncstr(output, "");
            skip_to_endif(state, true, &stopped_at_else);
            if (stopped_at_else)
            {
                output = skip_to_endif(state, false, &stopped_at_else);
            }
        }
        
        // print the output to the pre processor input
        ppimpl_printf(state, "%s", output->data);
    }
    else
        dhalt(ERR_PP_ASM_IF_PARAMETERS_INCORRECT, ppimpl_get_location(state));
    
    ppparam_free(result);
}
Exemple #3
0
struct process_parameter_results process_register(struct ast_node_register* param)
{
    struct process_parameter_results result;
    struct register_mapping* registr;

    if (param->bracketed)
        printd(LEVEL_VERBOSE, "[%s]", param->value);
    else
        printd(LEVEL_VERBOSE, "%s", param->value);

    registr = get_register_by_name(param->value, param->bracketed);

    if (registr == NULL)
    {
        // Must be a label.
        result.v = 0x0;
        result.v_extra = 0x0;
        result.v_extra_used = false;
        result.v_label = param->value;
        result.v_label_bracketed = param->bracketed;
        result.v_raw = NULL;
    }
    else if (registr->value == BRACKETS_UNSUPPORTED)
    {
        // Attempt to use a register in brackets that can't be.
        printd(LEVEL_VERBOSE, "\n");
        dhalt(ERR_BRACKETED_REGISTER_UNSUPPORTED, param->value);
    }
    else
    {
        // Must be a register.
        result.v = registr->value;
        result.v_extra = 0x0;
        result.v_extra_used = false;
        result.v_label = NULL;
        result.v_label_bracketed = false;
        result.v_raw = NULL;
    }

    return result;
}
Exemple #4
0
void* dtemu_create_context(const char* title, int width, int height, bool resizeable, void* ud)
{
    GLFWwindow* context = malloc(sizeof(GLFWwindow));

    if (!resizeable)
        glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
    *context = (GLFWwindow) glfwCreateWindow(width, height, GLFW_WINDOWED, title, NULL);
    
    if (*context == NULL)
        dhalt(ERR_COULD_NOT_CREATE_OPENGL_CONTEXT, "glfwCreateWindow returned NULL.");

    glfwSetWindowUserPointer(*context, ud);
    glfwMakeContextCurrent(*context);
    glfwSetWindowCloseCallback(&vm_hw_glfw_close_window_callback);
    glfwSetWindowSizeCallback(&vm_hw_glfw_resize_window_callback);
    glfwSwapInterval(0);

    glfwSetTime(0.0);

    return context;
}
Exemple #5
0
int main(int argc, char* argv[])
{
    // Define our variables.
    int nerrors, i;
    int32_t saved = 0; // The number of words saved during compression and optimization.
    struct errinfo* errval;
    const char* prepend = "error: ";
    const char* warnprefix = "no-";
    int msglen;
    char* msg;
    int target;

    // Define arguments.
    struct arg_lit* show_help = arg_lit0("h", "help", "Show this help.");
    struct arg_str* target_arg = arg_str0("l", "link-as", "target", "Link as the specified object, can be 'image', 'static' or 'kernel'.");
    struct arg_file* symbol_file = arg_file0("s", "symbols", "<file>", "Produce a combined symbol file (~triples memory usage!).");
    struct arg_str* symbol_ext = arg_str0(NULL, "symbol-extension", "ext", "When -s is used, specifies the extension for symbol files.  Defaults to \"dsym16\".");
    struct arg_file* input_files = arg_filen(NULL, NULL, "<file>", 1, 100, "The input object files.");
    struct arg_file* output_file = arg_file1("o", "output", "<file>", "The output file (or - to send to standard output).");
    struct arg_file* kernel_file = arg_file0("k", "kernel", "<file>", "Directly link in the specified kernel.");
    struct arg_file* jumplist_file = arg_file0("j", "jumplist", "<file>", "Link against the specified jumplist.");
    struct arg_str* warning_policies = arg_strn("W", NULL, "policy", 0, _WARN_COUNT * 2 + 10, "Modify warning policies.");
    struct arg_lit* keep_output_arg = arg_lit0(NULL, "keep-outputs", "Keep the .OUTPUT entries in the final static library (used for stdlib).");
    struct arg_lit* little_endian_mode = arg_lit0(NULL, "little-endian", "Use little endian serialization (for compatibility with older versions).");
    struct arg_lit* no_short_literals_arg = arg_lit0(NULL, "no-short-literals", "Do not compress literals to short literals.");
    struct arg_int* opt_level = arg_int0("O", NULL, "<level>", "The optimization level.");
    struct arg_lit* opt_mode = arg_lit0("S", NULL, "Favour runtime speed over size when optimizing.");
    struct arg_lit* verbose = arg_litn("v", NULL, 0, LEVEL_EVERYTHING - LEVEL_DEFAULT, "Increase verbosity.");
    struct arg_lit* quiet = arg_litn("q", NULL,  0, LEVEL_DEFAULT - LEVEL_SILENT, "Decrease verbosity.");
    struct arg_end* end = arg_end(20);
    void* argtable[] = { show_help, target_arg, keep_output_arg, little_endian_mode, opt_level, opt_mode, no_short_literals_arg,
                         symbol_ext, symbol_file, kernel_file, jumplist_file, warning_policies, output_file, input_files, verbose, quiet, end
                       };

    // Parse arguments.
    nerrors = arg_parse(argc, argv, argtable);

    version_print(bautofree(bfromcstr("Linker")));
    if (nerrors != 0 || show_help->count != 0)
    {
        if (show_help->count != 0)
            arg_print_errors(stdout, end, "linker");

        printd(LEVEL_DEFAULT, "syntax:\n    dtld");
        arg_print_syntax(stderr, argtable, "\n");
        printd(LEVEL_DEFAULT, "options:\n");
        arg_print_glossary(stderr, argtable, "    %-25s %s\n");
        arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0]));
        return 1;
    }

    // Set verbosity level.
    debug_setlevel(LEVEL_DEFAULT + verbose->count - quiet->count);

    // Set global path variable.
    osutil_setarg0(bautofree(bfromcstr(argv[0])));

    // Set endianness.
    isetmode(little_endian_mode->count == 0 ? IMODE_BIG : IMODE_LITTLE);

    // Set up warning policies.
    dsetwarnpolicy(warning_policies);

    // Set up error handling.
    if (dsethalt())
    {
        errval = derrinfo();

        // FIXME: Use bstrings here.
        msglen = strlen(derrstr[errval->errid]) + strlen(prepend) + 1;
        msg = malloc(msglen);
        memset(msg, '\0', msglen);
        strcat(msg, prepend);
        strcat(msg, derrstr[errval->errid]);
        printd(LEVEL_ERROR, msg, errval->errdata);

        // Handle the error.
        printd(LEVEL_ERROR, "linker: error occurred.\n");

        arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0]));
        return 1;
    }

    // Check to make sure target is correct.
    if (target_arg->count == 0)
        target = IMAGE_APPLICATION;
    else
    {
        if (strcmp(target_arg->sval[0], "image") == 0)
            target = IMAGE_APPLICATION;
        else if (strcmp(target_arg->sval[0], "static") == 0)
            target = IMAGE_STATIC_LIBRARY;
        else if (strcmp(target_arg->sval[0], "kernel") == 0)
            target = IMAGE_KERNEL;
        else
        {
            // Invalid option.
            dhalt(ERR_INVALID_TARGET_NAME, NULL);
        }
    }

    // Load all passed objects and use linker bin system to
    // produce result.
    bins_init();
    for (i = 0; i < input_files->count; i++)
        if (!bins_load(bautofree(bfromcstr(input_files->filename[i])), symbol_file->count > 0, (symbol_file->count > 0 && symbol_ext->count > 0) ? symbol_ext->sval[0] : "dsym16"))
            // Failed to load one of the input files.
            dhalt(ERR_BIN_LOAD_FAILED, input_files->filename[i]);
    bins_associate();
    bins_sectionize();
    bins_flatten(bautofree(bfromcstr("output")));
    if (target == IMAGE_KERNEL)
        bins_write_jump();
    saved = bins_optimize(
                opt_mode->count == 0 ? OPTIMIZE_SIZE : OPTIMIZE_SPEED,
                opt_level->count == 0 ? OPTIMIZE_NONE : opt_level->ival[0]);
    if (no_short_literals_arg->count == 0 && target != IMAGE_STATIC_LIBRARY)
        saved += bins_compress();
    else if (no_short_literals_arg->count == 0)
        dwarn(WARN_SKIPPING_SHORT_LITERALS_TYPE, NULL);
    else
        dwarn(WARN_SKIPPING_SHORT_LITERALS_REQUEST, NULL);
    bins_resolve(
        target == IMAGE_STATIC_LIBRARY,
        target == IMAGE_STATIC_LIBRARY);
    bins_save(
        bautofree(bfromcstr("output")),
        bautofree(bfromcstr(output_file->filename[0])),
        target,
        keep_output_arg->count > 0,
        symbol_file->count > 0 ? symbol_file->filename[0] : NULL,
        jumplist_file->count > 0 ? jumplist_file->filename[0] : NULL);
    bins_free();
    if (saved > 0)
        printd(LEVEL_DEFAULT, "linker: saved %i words during optimization.\n", saved);
    else if (saved < 0)
        printd(LEVEL_DEFAULT, "linker: increased by %i words during optimization.\n", -saved);

    arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0]));
    return 0;
}
Exemple #6
0
static void macro_handle(state_t* state, match_t* match, bool* reprocess)
{
    bstring name;
    bstring temp;
    list_t parameters;
    list_t arguments;
    bool getting_name = true;
    bool getting_parameters = false;
    bool getting_arguments = false;
    struct replace_info* info = match->userdata;
    int i = 0;
    int argument_brackets = 0;
    char c;
    char* start_loc;
    match_t* new_match;
    struct replace_info* new_info;

    // Parse the parameters out of the name.
    list_init(&parameters);
    temp = bfromcstr("");
    for (i = 0; i < blength(info->full); i++)
    {
        c = info->full->data[i];
        if (getting_name)
        {
            if (c == '(')
            {
                getting_name = false;
                getting_parameters = true;
                name = bstrcpy(temp);
                bassigncstr(temp, "");
            }
            else
                bconchar(temp, c);
        }
        else if (getting_parameters)
        {
            if (c == ',' || c == ')')
            {
                btrimws(temp);
                list_append(&parameters, bstrcpy(temp));
                bassigncstr(temp, "");
                if (c == ')')
                {
                    getting_parameters = false;
                    break;
                }
            }
            else
                bconchar(temp, c);
        }
    }

    // Attempt to accept an open bracket.
    c = ppimpl_get_input(state);
    while (c == '\1')
    {
        // Consume macro termination.
        i = 0;
        while (i < strlen("\1MACROTERMINATE\1"))
        {
            if (c != "\1MACROTERMINATE\1"[i++])
                dhalt(ERR_PP_EXPECTED_OPEN_BRACKET, ppimpl_get_location(state));
            c = ppimpl_get_input(state);
        }
        ppimpl_pop_scope(state);
    }
    if (c != '(')
        dhalt(ERR_PP_EXPECTED_OPEN_BRACKET, ppimpl_get_location(state));
    
    // Read arguments.
    getting_arguments = true;
    list_init(&arguments);
    start_loc = ppimpl_get_location(state);
    bassigncstr(temp, "");
    while (ppimpl_has_input(state) && getting_arguments)
    {
        c = ppimpl_get_input(state);

        if (c == '(')
        {
            argument_brackets++;
            bconchar(temp, c);
        }
        else if (c == ')' && argument_brackets != 0)
        {
            argument_brackets--;
            bconchar(temp, c);
        }
        else if (c == ')' && argument_brackets == 0)
        {
            list_append(&arguments, bstrcpy(temp));
            bassigncstr(temp, "");
            getting_arguments = false;
            break;
        }
        else if (c == ',' && argument_brackets == 0)
        {
            list_append(&arguments, bstrcpy(temp));
            bassigncstr(temp, "");
        }
        else
            bconchar(temp, c);
    }
    if (getting_arguments)
        dhalt(ERR_PP_NO_TERMINATING_BRACKET, start_loc);

    // Check to see if the argument count is correct.
    if (list_size(&arguments) > list_size(&parameters))
        dhalt(ERR_PP_TOO_MANY_PARAMETERS, start_loc);
    else if (list_size(&arguments) < list_size(&parameters))
        dhalt(ERR_PP_NOT_ENOUGH_PARAMETERS, start_loc);
    free(start_loc);

    // Create a new scope for macro evaluation.
    ppimpl_push_scope(state, true);

    // Define the new handlers.
    for (i = 0; i < list_size(&parameters); i++)
    {
        new_info = malloc(sizeof(struct replace_info));
        new_info->full = list_get_at(&parameters, i);
        new_info->replacement = list_get_at(&arguments, i);
        if (biseq(new_info->full, new_info->replacement))
        {
            free(new_info);
            continue;
        }
        new_match = malloc(sizeof(match_t));
        new_match->text = bautofree(list_get_at(&parameters, i));
        new_match->handler = replace_handle;
        new_match->line_start_only = false;
        new_match->identifier_only = true;
        new_match->userdata = new_info;
        new_match->case_insensitive = false;
        ppimpl_register(state, new_match);
    }
    
    // Print out the macro evaluation and terminator.
    ppimpl_printf(state, "%s\1MACROTERMINATE\1", info->replacement->data);
}
Exemple #7
0
static void define_handle(state_t* state, match_t* match, bool* reprocess)
{
    // We need to parse this manually because we're interested in getting
    // the first word and then all of the content until a line that doesn't end
    // with "\".
    bstring name = bfromcstr("");
    bstring word = bfromcstr("");
    bstring definition = bfromcstr("");
    bool getting_word = true;
    bool getting_definition = true;
    bool is_macro = false;
    match_t* new_match;
    struct replace_info* info;

    // Get the first word.
    while (getting_word)
    {
        char c = ppimpl_get_input(state);
        bconchar(word, c);
        if (!is_macro && c != '(')
            bconchar(name, c);
        bltrimws(word);

        // Handle termination.
        if (blength(word) > 0 && (c == ' ' || c == '\t') && !is_macro)
        {
            // End of word.
            btrimws(word);
            btrimws(name);
            getting_word = false;
        }
        else if (blength(word) > 0 && c == '(' && !is_macro)
        {
            // Start of macro.
            is_macro = true;
        }
        else if (blength(word) > 0 && c == '(' && is_macro)
        {
            // Second ( in a macro; error.
            dhalt(ERR_PP_MACRO_MALFORMED, ppimpl_get_location(state));
        }
        else if (blength(word) > 0 && c == ')' && is_macro)
        {
            // End of macro name.
            btrimws(word);
            btrimws(name);
            getting_word = false;
        }
        else if (blength(word) == 0 && c == '\n')
            dhalt(ERR_PP_C_DEFINE_PARAMETERS_INCORRECT, ppimpl_get_location(state));
        else if (blength(word) > 0 && c == '\n')
        {
            // End of word.
            btrimws(word);
            btrimws(name);
            getting_word = false;
            getting_definition = false;
            ppimpl_printf(state, "\n");
        }
    }

    // Get the definition.
    while (getting_definition)
    {
        char c = ppimpl_get_input(state);
        bconchar(definition, c);
        bltrimws(definition);
        
        if (c == '\n')
        {
            if (blength(definition) > 1 && definition->data[blength(definition) - 2] == '\\')
            {
                // Remove the new slash.
                bdelete(definition, blength(definition) - 2, 1);
                ppimpl_oprintf(state, "\n");
            }
            else
            {
                btrimws(definition);
                getting_definition = false;
                ppimpl_printf(state, "\n");
            }
        }
        else if (c == '/' || c == '*')
        {
            if (blength(definition) > 1 && definition->data[blength(definition) - 2] == '/')
            {
                // a line or block comment
                ppimpl_iprintf(state, "/%c", c);
                // remove the slashes
                bdelete(definition, blength(definition) - 2, 2);
                btrimws(definition);
                getting_definition = false;
            }
        }
    }
    
    if (blength(definition) == 0 && !is_macro)
        bassigncstr(definition, "1");
        

    // Create the new replacement handler.
    info = malloc(sizeof(struct replace_info));
    info->full = word;
    info->replacement = definition;
    if (biseq(info->full, info->replacement))
    {
        free(info);
        return;
    }
    new_match = malloc(sizeof(match_t));
    new_match->text = bautofree(name);
    if (is_macro)
        new_match->handler = macro_handle;
    else
        new_match->handler = replace_handle;
    new_match->line_start_only = false;
    new_match->identifier_only = true;
    new_match->userdata = info;
    new_match->case_insensitive = false;
    ppimpl_register(state, new_match);
    *reprocess = true;
}
Exemple #8
0
int main(int argc, char* argv[])
{
    // Define our variables.
    FILE* load;
    uint16_t flash[0x10000];
    char leading[0x100];
    unsigned int i;
    bool uread = true;
    vm_t* vm;
    int nerrors;
    bstring ss, st;
    host_context_t* dtemu = malloc(sizeof(host_context_t));
    const char* warnprefix = "no-";

    // Define arguments.
    struct arg_lit* show_help = arg_lit0("h", "help", "Show this help.");
    struct arg_file* input_file = arg_file1(NULL, NULL, "<file>", "The input file, or - to read from standard input.");
    struct arg_file* execution_dump_file = arg_file0("e", "execution-dump", "<file>", "Produce a very large execution dump file.");
    struct arg_lit* debug_mode = arg_lit0("d", "debug", "Show each executed instruction.");
    struct arg_lit* terminate_mode = arg_lit0("t", "show-on-terminate", "Show state of machine when program is terminated.");
    struct arg_lit* headless_mode = arg_lit0("h", "headless", "Run machine witout displaying monitor and SPED output");
    struct arg_lit* legacy_mode = arg_lit0("l", "legacy", "Automatically initialize hardware to legacy values.");
    struct arg_str* warning_policies = arg_strn("W", NULL, "policy", 0, _WARN_COUNT * 2 + 10, "Modify warning policies.");
    struct arg_lit* little_endian_mode = arg_lit0(NULL, "little-endian", "Use little endian serialization (for compatibility with older versions).");
    struct arg_lit* verbose = arg_litn("v", NULL, 0, LEVEL_EVERYTHING - LEVEL_DEFAULT, "Increase verbosity.");
    struct arg_lit* quiet = arg_litn("q", NULL,  0, LEVEL_DEFAULT - LEVEL_SILENT, "Decrease verbosity.");
    struct arg_int* radiation = arg_intn("r", NULL, "<n>", 0, 1, "Radiation factor (higher is less radiation)");
    struct arg_lit* catch_fire = arg_lit0("c", "catch-fire", "The virtual machine should catch fire instead of halting.");
    struct arg_end* end = arg_end(20);
    void* argtable[] = { input_file, warning_policies, debug_mode, execution_dump_file, terminate_mode, headless_mode, legacy_mode, little_endian_mode, radiation, catch_fire, verbose, quiet, end };

    // Parse arguments.
    nerrors = arg_parse(argc, argv, argtable);

    if (nerrors != 0 || show_help->count != 0)
    {
        if (show_help->count != 0)
            arg_print_errors(stdout, end, "emulator");

        printd(LEVEL_DEFAULT, "syntax:\n    dtemu");
        arg_print_syntax(stderr, argtable, "\n");
        printd(LEVEL_DEFAULT, "options:\n");
        arg_print_glossary(stderr, argtable, "      %-25s %s\n");
        arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0]));
        return 1;
    }

    // Set verbosity level.
    debug_setlevel(LEVEL_DEFAULT + verbose->count - quiet->count);
    
    // Show version information.
    version_print(bautofree(bfromcstr("Emulator")));

    // Set global path variable.
    osutil_setarg0(bautofree(bfromcstr(argv[0])));

    // Set endianness.
    isetmode(little_endian_mode->count == 0 ? IMODE_BIG : IMODE_LITTLE);

    // Set up warning policies.
    dsetwarnpolicy(warning_policies);
    
    // Set up error handling.
    if (dsethalt())
    {
        // Handle the error.
        dautohandle();
        printd(LEVEL_ERROR, "emulator: error occurred.\n");

        arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0]));
        return 1;
    }

    // Zero out the flash space.
    for (i = 0; i < 0x10000; i++)
        flash[i] = 0x0;

    // Zero out the leading space.
    for (i = 0; i < 0x100; i++)
        leading[i] = 0x0;

    // Load from either file or stdin.
    if (strcmp(input_file->filename[0], "-") != 0)
    {
        // Open file.
        load = fopen(input_file->filename[0], "rb");

        if (load == NULL)
            dhalt(ERR_EMU_LOAD_FILE_FAILED, input_file->filename[0]);
    }
    else
    {
        // Windows needs stdin in binary mode.
#ifdef _WIN32
        _setmode(_fileno(stdin), _O_BINARY);
#endif

        // Set load to stdin.
        load = stdin;
    }
    
    // Read leading component.
    for (i = 0; i < strlen(ldata_objfmt); i++)
        leading[i] = fgetc(load);
    fseek(load, 0, SEEK_SET);

    // Read up to 0x10000 words.
    for (i = 0; i < 0x10000 && !feof(load); i++)
        iread(&flash[i], load);
    fclose(load);

    // Check to see if the first X bytes matches the header
    // for intermediate code and stop if it does.
    ss = bfromcstr("");
    st = bfromcstr(ldata_objfmt);
    for (i = 0; i < strlen(ldata_objfmt); i++)
        bconchar(ss, leading[i]);
    if (biseq(ss, st))
        dhalt(ERR_INTERMEDIATE_EXECUTION, NULL);

    // Set up the host context.
    glfwInit();
    dtemu->create_context = &dtemu_create_context;
    dtemu->activate_context = &dtemu_activate_context;
    dtemu->swap_buffers = &dtemu_swap_buffers;
    dtemu->destroy_context = &dtemu_destroy_context;
    dtemu->get_ud = &dtemu_get_ud;

    // And then use the VM.
    vm = vm_create();
    vm->debug = (debug_mode->count > 0);
    vm_flash(vm, flash);

    // Set radiation and catch fire settings.
    if (radiation->count == 1)
        vm->radiation_factor = radiation->ival[0];
    if (catch_fire->count == 1)
        vm->can_fire = true;

    // Init hardware.
    vm_hw_clock_init(vm);

    if (headless_mode->count < 1)
        vm->host = dtemu;

    vm_hw_sped3_init(vm);
    vm_hw_lem1802_init(vm);
    vm_hw_m35fd_init(vm);
    vm_hw_lua_init(vm);

    if (legacy_mode->count > 0)
    {
        for (i = 0; i < vm_hw_count(vm); i++) {

            hw_t* device = vm_hw_get_device(vm, i);
            if (device == NULL)
                continue;

            if (device->id == 0x7349F615 && device->manufacturer == 0x1C6C8B36)
            {
                vm_hw_lem1802_mem_set_screen((struct lem1802_hardware*)device->userdata, 0x8000);
                break;
            }
        }
    }

    vm_execute(vm, execution_dump_file->count > 0 ? execution_dump_file->filename[0] : NULL);

    if (terminate_mode->count > 0)
    {
        fprintf(stderr, "\n");
        fprintf(stderr, "A:   0x%04X     [A]:    0x%04X\n", vm->registers[REG_A], vm->ram[vm->registers[REG_A]]);
        fprintf(stderr, "B:   0x%04X     [B]:    0x%04X\n", vm->registers[REG_B], vm->ram[vm->registers[REG_B]]);
        fprintf(stderr, "C:   0x%04X     [C]:    0x%04X\n", vm->registers[REG_C], vm->ram[vm->registers[REG_C]]);
        fprintf(stderr, "X:   0x%04X     [X]:    0x%04X\n", vm->registers[REG_X], vm->ram[vm->registers[REG_X]]);
        fprintf(stderr, "Y:   0x%04X     [Y]:    0x%04X\n", vm->registers[REG_Y], vm->ram[vm->registers[REG_Y]]);
        fprintf(stderr, "Z:   0x%04X     [Z]:    0x%04X\n", vm->registers[REG_Z], vm->ram[vm->registers[REG_Z]]);
        fprintf(stderr, "I:   0x%04X     [I]:    0x%04X\n", vm->registers[REG_I], vm->ram[vm->registers[REG_I]]);
        fprintf(stderr, "J:   0x%04X     [J]:    0x%04X\n", vm->registers[REG_J], vm->ram[vm->registers[REG_J]]);
        fprintf(stderr, "PC:  0x%04X     SP:    0x%04X\n", vm->pc, vm->sp);
        fprintf(stderr, "EX:  0x%04X     IA:    0x%04X\n", vm->ex, vm->ia);
    }

    vm_hw_lua_free(vm);
    vm_free(vm);

    arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0]));
    glfwTerminate();
    return 0;
}
Exemple #9
0
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);
        }
    }
}
Exemple #10
0
struct process_parameters_results process_parameters(struct ast_node_parameters* params)
{
    struct process_parameters_results result;
    struct process_parameter_results t;
    reverse_parameters(params);
    result.raw = NULL;

    if (params->last != NULL)
    {
        t = process_parameter(params->last);

        if (t.v_raw)
        {
            printd(LEVEL_VERBOSE, "\n");
            dhalt(ERR_GEN_UNSUPPORTED_PARAMETER, NULL);
        }

        result.a = t.v;
        result.a_extra = t.v_extra;
        result.a_extra_used = t.v_extra_used;
        result.a_label = t.v_label;
        result.a_label_bracketed = t.v_label_bracketed;

        if (params->last->prev != NULL)
        {
            t = process_parameter(params->last->prev);

            if (t.v_raw)
            {
                printd(LEVEL_VERBOSE, "\n");
                dhalt(ERR_GEN_UNSUPPORTED_PARAMETER, NULL);
            }

            result.b = t.v;
            result.b_extra = t.v_extra;
            result.b_extra_used = t.v_extra_used;
            result.b_label = t.v_label;
            result.b_label_bracketed = t.v_label_bracketed;
        }
        else
        {
            result.b = 0x0;
            result.b_extra = 0x0;
            result.b_extra_used = false;
            result.b_label = NULL;
            result.b_label_bracketed = false;
        }
    }
    else
    {
        result.a = 0x0;
        result.a_extra = 0x0;
        result.a_extra_used = false;
        result.a_label = NULL;
        result.b_label_bracketed = false;
        result.b = 0x0;
        result.b_extra = 0x0;
        result.b_extra_used = false;
        result.b_label = NULL;
        result.b_label_bracketed = false;
    }

    return result;
}
Exemple #11
0
struct process_parameter_results process_address(struct ast_node_address* param)
{
    struct process_parameter_results result;
    struct register_mapping* registr;
    bstring btmp = NULL;
    result.v_raw = NULL;

    if (param->value != NULL)
        btmp = expr_representation(param->value);

    if (param->bracketed && param->added)
    {
        // This is of the form [0x1000+I].
        registr = get_register_by_name_next(param->addcmpt);

        if (registr == NULL)
        {
            // Attempt to use a label in square brackets.  Convert this
            // to an expression and then reinvoke ourselves with the
            // evaluated value.
            param->value = expr_new(expr_new_label(bautofree(bfromcstr(param->addcmpt))), EXPR_OP_ADD, param->value);
            param->addcmpt = "";
            param->added = 0;
            param->bracketed = 0;

            bdestroy(btmp);
            return process_address(param);
        }
        else if (registr->value == VALUE_NEXT_UNSUPPORTED)
        {
            // Attempt to use a register in brackets that can't be.
            printd(LEVEL_VERBOSE, "\n");
            dhalt(ERR_NEXTED_REGISTER_UNSUPPORTED, param->addcmpt);
        }

        printd(LEVEL_VERBOSE, "[%s+%s]", btmp->data, registr->name);
        result.v = registr->value;
        result.v_extra = param->value;
        result.v_extra_used = true;
        result.v_label = NULL;
    }
    else
    {
        // This is either the form 0x1000 or [0x1000].
        if (param->bracketed)
        {
            printd(LEVEL_VERBOSE, "[%s]", btmp->data);
            result.v = NXT;
        }
        else
        {
            printd(LEVEL_VERBOSE, "%s", btmp->data);
            result.v = NXT_LIT;
        }

        result.v_extra = param->value;
        result.v_extra_used = true;
        result.v_label = NULL;
    }

    if (btmp != NULL)
        bdestroy(btmp);

    return result;
}
Exemple #12
0
static bstring skip_to_endif(state_t* state, bool stop_at_else, bool* stopped_at_else)
{
    char c;
    bool fresh_line = true;
    bstring temp = bfromcstr("");
    bstring temp_output = bfromcstr("");
    bstring output = bfromcstr("");
    int if_open = 1; 
    
    while (ppimpl_has_input(state))
    {
        c = ppimpl_get_input(state);
        switch(c)
        {
            case '#':
            case '.':
                if (!fresh_line)
                {
                    bconchar(output, c);
                    break;
                }
                bassigncstr(temp_output, "#");
                // first skip spaces
                while (ppimpl_has_input(state))
                {
                    c = ppimpl_get_input(state);
                    bconchar(temp_output, c);
                    if (c != ' ' && c != '\t')
                        break;
                }
                // read pp directive
                bassigncstr(temp, "");
                bconchar(temp, c);
                while (ppimpl_has_input(state))
                {
                    c = ppimpl_get_input(state);
                    bconchar(temp_output, c);
                    if (c == ' ' || c == '\t' || c == '\n')
                        break;
                    bconchar(temp, c);
                }
                
                btolower(temp);
                
                if (biseq(temp, bfromcstr("endif")))
                {
                    if_open--;
                    if (if_open == 0)
                    {
                        if (c != '\n') skip_to_endln(state);
                        *stopped_at_else = false;
                        return output;
                    }
                }
                else if (biseq(temp, bfromcstr("if")))
                {
                    if_open++;
                }
                else if (biseq(temp, bfromcstr("else")) && stop_at_else)
                {
                    if (if_open == 1)
                    {
                        if (c != '\n') skip_to_endln(state);
                        *stopped_at_else = true;
                        return output;
                    }
                }
                bconcat(output, temp_output);
                fresh_line = (c == '\n');
                break;
                
            case '\n':
                fresh_line = true;
                bconchar(output, c);
                break;
            case ' ':
            case '\t':
                bconchar(output, c);
                break;
                
            default:
                fresh_line = false;
                bconchar(output, c);
                break;
        }
    }
    
    // No .ENDIF was found.
    dhalt(ERR_PP_ASM_NO_ENDIF_TO_IF, ppimpl_get_location(state));

    // dhalt will trigger before this, but the compiler warns about
    // control potentially reaching the end of this function.
    return NULL;
}
Exemple #13
0
static void endif_handle(state_t* state, match_t* match, bool* reprocess)
{
    // free else encountered
    dhalt(ERR_PP_ASM_ENDIF_NO_IF, ppimpl_get_location(state));
}