Example #1
0
void mon_memory_move(MON_ADDR start_addr, MON_ADDR end_addr, MON_ADDR dest)
{
    unsigned int i, dst;
    int len;
    WORD start;
    MEMSPACE src_mem, dest_mem;
    BYTE *buf;

    len = mon_evaluate_address_range(&start_addr, &end_addr, TRUE, -1);
    if (len <= 0) {
        mon_out("Invalid range.\n");
        return;
    }
    src_mem = addr_memspace(start_addr);
    start = addr_location(start_addr);

    mon_evaluate_default_addr(&dest);
    dst = addr_location(dest);
    dest_mem = addr_memspace(dest);

    buf = lib_malloc(sizeof(BYTE) * len);

    for (i = 0; (int)i < len; i++) {
        buf[i] = mon_get_mem_val(src_mem, (WORD)ADDR_LIMIT(start + i));
    }

    for (i = 0; (int)i < len; i++) {
        mon_set_mem_val(dest_mem, (WORD)ADDR_LIMIT(dst + i), buf[i]);
    }

    lib_free(buf);
}
Example #2
0
void mon_memory_compare(MON_ADDR start_addr, MON_ADDR end_addr, MON_ADDR dest)
{
    WORD start;
    MEMSPACE src_mem, dest_mem;
    BYTE byte1, byte2;
    unsigned int i, dst;
    int len;

    len = mon_evaluate_address_range(&start_addr, &end_addr, TRUE, -1);
    if (len < 0) {
        mon_out("Invalid range.\n");
        return;
    }
    src_mem = addr_memspace(start_addr);
    start = addr_location(start_addr);

    mon_evaluate_default_addr(&dest);
    dst = addr_location(dest);
    dest_mem = addr_memspace(dest);

    for (i = 0; (int)i < len; i++) {
        byte1 = mon_get_mem_val(src_mem, (WORD)ADDR_LIMIT(start + i));
        byte2 = mon_get_mem_val(dest_mem, (WORD)ADDR_LIMIT(dst + i));

        if (byte1 != byte2) {
            mon_out("$%04x $%04x: %02x %02x\n",
                    ADDR_LIMIT(start + i), ADDR_LIMIT(dst + i), byte1, byte2);
        }
    }
}
Example #3
0
void mon_disassemble_lines(MON_ADDR start_addr, MON_ADDR end_addr)
{
    MEMSPACE mem;
    long len, i, bytes;

    len = mon_evaluate_address_range(&start_addr, &end_addr, FALSE, DEFAULT_DISASSEMBLY_SIZE);

    if (len < 0) {
        log_error(LOG_ERR, "Invalid address range");
        return;
    }

    mem = addr_memspace(start_addr);
    dot_addr[mem] = start_addr;

    i = 0;
    while (i <= len) {
        bytes = mon_disassemble_instr(dot_addr[mem]);
        i += bytes;
        mon_inc_addr_location(&(dot_addr[mem]), bytes);
        if (mon_stop_output != 0) {
            break;
        }
    }
}
Example #4
0
static void print_checkpoint_info(breakpoint_t *bp)
{
    if (bp->trace) {
        mon_out("TRACE: ");
    } else if (bp->watch_load || bp->watch_store) {
        mon_out("WATCH: ");
    } else {
        if (bp->temporary)
            mon_out("UNTIL: ");
        else
            mon_out("BREAK: ");
    }
    mon_out("%d %s:$%04x",bp->brknum,
        mon_memspace_string[addr_memspace(bp->start_addr)],addr_location(bp->start_addr));
    if (mon_is_valid_addr(bp->end_addr) && (bp->start_addr != bp->end_addr))
        mon_out("-$%04x",addr_location(bp->end_addr));

    if (bp->watch_load)
        mon_out(" load");
    if (bp->watch_store)
        mon_out(" store");

    mon_out("   %s\n", (bp->enabled==e_ON) ? "enabled" : "disabled");

    if (bp->condition) {
        mon_out("\tCondition: ");
        mon_print_conditional(bp->condition);
        mon_out("\n");
    }
    if (bp->command)
        mon_out("\tCommand: %s\n", bp->command);
}
Example #5
0
static 
int breakpoint_add_checkpoint(MON_ADDR start_addr, MON_ADDR end_addr,
                                  bool is_trace, bool is_load, bool is_store,
                                  bool is_temp, bool do_print)
{
    breakpoint_t *new_bp;
    MEMSPACE mem;
    long len;

    len = mon_evaluate_address_range(&start_addr, &end_addr, FALSE, 0);
    new_bp = (breakpoint_t *)lib_malloc(sizeof(breakpoint_t));

    new_bp->brknum = breakpoint_count++;
    new_bp->start_addr = start_addr;
    new_bp->end_addr = end_addr;
    new_bp->trace = is_trace;
    new_bp->enabled = e_ON;
    new_bp->hit_count = 0;
    new_bp->ignore_count = 0;
    new_bp->condition = NULL;
    new_bp->command = NULL;
    new_bp->watch_load = is_load;
    new_bp->watch_store = is_store;
    new_bp->temporary = is_temp;

    mem = addr_memspace(start_addr);
    if (!is_load && !is_store) {
        if (!any_breakpoints(mem)) {
            monitor_mask[mem] |= MI_BREAK;
            interrupt_monitor_trap_on(mon_interfaces[mem]->int_status);
        }

        add_to_checkpoint_list(&(breakpoints[mem]), new_bp);
    } else {
        if (!any_watchpoints(mem)) {
            monitor_mask[mem] |= MI_WATCH;
            mon_interfaces[mem]->toggle_watchpoints_func(1,
                mon_interfaces[mem]->context);
            interrupt_monitor_trap_on(mon_interfaces[mem]->int_status);
        }

        if (is_load)
            add_to_checkpoint_list(&(watchpoints_load[mem]), new_bp);
        if (is_store)
            add_to_checkpoint_list(&(watchpoints_store[mem]), new_bp);
    }

    if (is_temp)
        exit_mon = 1;

    if (do_print)
        print_checkpoint_info(new_bp);

    return new_bp->brknum;
}
Example #6
0
mon_breakpoint_type_t mon_breakpoint_is(MON_ADDR address)
{
    MEMSPACE mem = addr_memspace(address);
    WORD addr = addr_location(address);
    checkpoint_list_t *ptr;

    ptr = search_checkpoint_list(breakpoints[mem], addr);

    if (!ptr)
        return BP_NONE;

    return (ptr->checkpt->enabled == e_ON) ? BP_ACTIVE : BP_INACTIVE;
}
Example #7
0
void mon_breakpoint_unset(MON_ADDR address)
{
    MEMSPACE mem = addr_memspace(address);
    WORD addr = addr_location(address);
    checkpoint_list_t *ptr;

    ptr = search_checkpoint_list(breakpoints[mem], addr);

    if (ptr) {
        /* there's a breakpoint, so remove it */
        remove_checkpoint_from_list( &breakpoints[mem], ptr->checkpt );
    }
}
Example #8
0
void mon_breakpoint_disable(MON_ADDR address)
{
    MEMSPACE mem = addr_memspace(address);
    WORD addr = addr_location(address);
    checkpoint_list_t *ptr;

    ptr = search_checkpoint_list(breakpoints[mem], addr);

    if (ptr) {
        /* there's a breakpoint, so disable it */
        ptr->checkpt->enabled = e_OFF;
    }
}
Example #9
0
void mon_memory_hunt(MON_ADDR start_addr, MON_ADDR end_addr,
                     unsigned char *data)
{
    BYTE *buf;
    WORD start, next_read;
    MEMSPACE mem;
    unsigned int i;
    int len;

    len = mon_evaluate_address_range(&start_addr, &end_addr, TRUE, -1);
    if (len < 0 || len < (int)(data_buf_len)) {
        mon_out("Invalid range.\n");
        return;
    }
    mem = addr_memspace(start_addr);
    start = addr_location(start_addr);

    buf = lib_malloc(sizeof(BYTE) * data_buf_len);

    /* Fill buffer */
    for (i = 0; i < data_buf_len; i++) {
        buf[i] = mon_get_mem_val(mem, (WORD)ADDR_LIMIT(start + i));
    }

    /* Do compares */
    next_read = start + (WORD)data_buf_len;

    for (i = 0; i <= (len - data_buf_len); i++, next_read++) {
        int not_found = 0;
        unsigned int j;
        for (j = 0; j < data_buf_len; j++) {
            if ((buf[j] & data_mask_buf[j]) != data_buf[j]) {
                not_found = 1;
                break;
            }
        }
        if (!not_found) {
            mon_out("%04x\n", ADDR_LIMIT(start + i));
        }

        if (data_buf_len > 1) {
            memmove(&(buf[0]), &(buf[1]), data_buf_len - 1);
        }
        buf[data_buf_len - 1] = mon_get_mem_val(mem, next_read);
    }

    mon_clear_buffer();
    lib_free(buf);
}
Example #10
0
void mon_breakpoint_delete_checkpoint(int brknum)
{
    int i;
    breakpoint_t *bp = NULL;
    MEMSPACE mem;

    if (brknum == -1) {
        /* Add user confirmation here. */
        mon_out("Deleting all breakpoints\n");
        for (i = 1; i < breakpoint_count; i++) {
            bp = find_checkpoint(i);
            if (bp)
                mon_breakpoint_delete_checkpoint(i);
        }
    }
    else if (!(bp = find_checkpoint(brknum))) {
        mon_out("#%d not a valid breakpoint\n", brknum);
        return;
    } else {
        mem = addr_memspace(bp->start_addr);

        if (!(bp->watch_load) && !(bp->watch_store)) {
            remove_checkpoint_from_list(&(breakpoints[mem]), bp);

            if (!any_breakpoints(mem)) {
                monitor_mask[mem] &= ~MI_BREAK;
                if (!monitor_mask[mem])
                    interrupt_monitor_trap_off(mon_interfaces[mem]->int_status);            }
        } else {
            if (bp->watch_load)
                remove_checkpoint_from_list(&(watchpoints_load[mem]), bp);
            if (bp->watch_store)
                remove_checkpoint_from_list(&(watchpoints_store[mem]), bp);

            if (!any_watchpoints(mem)) {
                monitor_mask[mem] &= ~MI_WATCH;
                mon_interfaces[mem]->toggle_watchpoints_func(0,
                    mon_interfaces[mem]->context);

                if (!monitor_mask[mem])
                    interrupt_monitor_trap_off(mon_interfaces[mem]->int_status);            }
        }
    }
    if (bp != NULL) {
        mon_delete_conditional(bp->condition);
        if (bp->command)
            lib_free(bp->command);
    }
}
static
int breakpoint_add_checkpoint(MON_ADDR start_addr, MON_ADDR end_addr,
                              bool stop, MEMORY_OP memory_op,
                              bool is_temp, bool do_print)
{
    checkpoint_t *new_cp;
    MEMSPACE mem;

    mon_evaluate_address_range(&start_addr, &end_addr, FALSE, 0);
    new_cp = lib_malloc(sizeof(checkpoint_t));

    new_cp->checknum = breakpoint_count++;
    new_cp->start_addr = start_addr;
    new_cp->end_addr = end_addr;
    new_cp->stop = stop;
    new_cp->enabled = e_ON;
    new_cp->hit_count = 0;
    new_cp->ignore_count = 0;
    new_cp->condition = NULL;
    new_cp->command = NULL;
    new_cp->check_load = memory_op & e_load;
    new_cp->check_store = memory_op & e_store;
    new_cp->check_exec = memory_op & e_exec;
    new_cp->temporary = is_temp;

    mem = addr_memspace(start_addr);
    if (new_cp->check_exec) {
        add_to_checkpoint_list(&(breakpoints[mem]), new_cp);
    }
    if (new_cp->check_load) {
        add_to_checkpoint_list(&(watchpoints_load[mem]), new_cp);
    }
    if (new_cp->check_store) {
        add_to_checkpoint_list(&(watchpoints_store[mem]), new_cp);
    }

    update_checkpoint_state(mem);

    if (is_temp) {
        exit_mon = 1;
    }

    if (do_print) {
        print_checkpoint_info(new_cp);
    }

    return new_cp->checknum;
}
Example #12
0
void mon_breakpoint_set(MON_ADDR address)
{
    MEMSPACE mem = addr_memspace(address);
    WORD addr = addr_location(address);
    checkpoint_list_t *ptr;

    ptr = search_checkpoint_list(breakpoints[mem], addr);

    if (ptr) {
        /* there's a breakpoint, so enable it */
        ptr->checkpt->enabled = e_ON;
    } else {
        /* there's no breakpoint, so set a new one */
        breakpoint_add_checkpoint(address, address,
                                  TRUE, e_exec, FALSE, FALSE);
    }
}
static void print_checkpoint_info(checkpoint_t *cp)
{
    if (!cp->stop) {
        mon_out("TRACE: ");
    } else if (cp->check_load || cp->check_store) {
        mon_out("WATCH: ");
    } else {
        if (cp->temporary) {
            mon_out("UNTIL: ");
        } else {
            mon_out("BREAK: ");
        }
    }
    mon_out("%d  %s:$%04x", cp->checknum,
            mon_memspace_string[addr_memspace(cp->start_addr)], addr_location(cp->start_addr));
    if (mon_is_valid_addr(cp->end_addr) && (cp->start_addr != cp->end_addr)) {
        mon_out("-$%04x", addr_location(cp->end_addr));
    }

    mon_out(cp->stop ? "  (Stop on" : "  (Trace");
    if (cp->check_load) {
        mon_out(" load");
    }
    if (cp->check_store) {
        mon_out(" store");
    }
    if (cp->check_exec) {
        mon_out(" exec");
    }

    mon_out(")");
    if (cp->enabled != e_ON) {
        mon_out(" disabled");
    }
    mon_out("\n");

    if (cp->condition) {
        mon_out("\tCondition: ");
        mon_print_conditional(cp->condition);
        mon_out("\n");
    }
    if (cp->command) {
        mon_out("\tCommand: %s\n", cp->command);
    }
}
Example #14
0
unsigned mon_disassemble_instr(MON_ADDR addr)
{
    MEMSPACE mem;
    WORD loc;
    char *label;
    unsigned opc_size;

    mem = addr_memspace(addr);
    loc = addr_location(addr);

    /* Print the label for this location - if we have one */
    label = mon_symbol_table_lookup_name(mem, loc);
    if (label) {
        mon_out(".%s:%04x   %s:\n", mon_memspace_string[mem], loc, label);
    }

    /* Print the disassembled instruction */
    mon_out("%s\n", mon_disassemble_instr_interal(&opc_size, addr));

    return opc_size;
    /* asm_addr_mode_get_size(asm_opcode_info_get(op)->addr_mode); */
}
Example #15
0
static void remove_checkpoint(checkpoint_t *cp)
{
    MEMSPACE mem;

    mem = addr_memspace(cp->start_addr);

    mon_delete_conditional(cp->condition);
    lib_free(cp->command);
    cp->command = NULL;

    if (cp->check_exec) {
        remove_checkpoint_from_list(&(breakpoints[mem]), cp);
    }
    if (cp->check_load) {
        remove_checkpoint_from_list(&(watchpoints_load[mem]), cp);
    }
    if (cp->check_store) {
        remove_checkpoint_from_list(&(watchpoints_store[mem]), cp);
    }

    update_checkpoint_state(mem);
}
Example #16
0
/* display binary data (sprites/chars) */
void mon_memory_display_data(MON_ADDR start_addr, MON_ADDR end_addr,
                             unsigned int x, unsigned int y)
{
    unsigned i, j, len, cnt = 0;
    WORD addr = 0;
    MEMSPACE mem;

    len = mon_evaluate_address_range(&start_addr, &end_addr, FALSE,
                                     (WORD)((x * y) / 8));
    mem = addr_memspace(start_addr);
    addr = addr_location(start_addr);

    while (cnt < len) {
        for (i = 0; i < y; i++) {
            mon_out(">%s:%04x ", mon_memspace_string[mem], addr);
            for (j = 0; j < (x / 8); j++) {
                mon_print_bin(mon_get_mem_val(mem,
                                              (WORD)(ADDR_LIMIT(addr + j))), '.', '*');
                cnt++;
            }
            mon_out("\n");
            addr = ADDR_LIMIT(addr + (x / 8));
            if (mon_stop_output != 0) {
                break;
            }
        }

        mon_out("\n");
        if (mon_stop_output != 0) {
            break;
        }
    }

    if ((x == 24) && (y == 21)) {
        addr++; /* continue at next even address when showing sprites */
    }
    set_addr_location(&(dot_addr[mem]), addr);
}
Example #17
0
void mon_memory_fill(MON_ADDR start_addr, MON_ADDR end_addr,
                     unsigned char *data)
{
    WORD start;
    MEMSPACE dest_mem;
    unsigned int i, mon_index;
    int len;

    len = mon_evaluate_address_range(&start_addr, &end_addr, FALSE,
                                     (WORD)data_buf_len);
    if (len < 0) {
        mon_out("Invalid range.\n");
        return;
    }
    start = addr_location(start_addr);

    if (!mon_is_valid_addr(start_addr)) {
        mon_out("Invalid start address\n");
        return;
    }

    dest_mem = addr_memspace(start_addr);

    i = 0;
    mon_index = 0;
    while ((int)i < len) {
        mon_set_mem_val(dest_mem, (WORD)ADDR_LIMIT(start + i),
                        data_buf[mon_index++]);
        if (mon_index >= data_buf_len) {
            mon_index = 0;
        }
        i++;
    }

    mon_clear_buffer();
}
Example #18
0
static const char* mon_disassemble_instr_interal(unsigned *opc_size, MON_ADDR addr)
{
    static char buff[256];
    BYTE opc[5];
    MEMSPACE mem;
    WORD loc;
    int hex_mode = 1;
    const char *dis_inst;

    mem = addr_memspace(addr);
    loc = addr_location(addr);

    opc[0] = mon_get_mem_val(mem, loc);
    opc[1] = mon_get_mem_val(mem, (WORD)(loc + 1));
    opc[2] = mon_get_mem_val(mem, (WORD)(loc + 2));
    opc[3] = mon_get_mem_val(mem, (WORD)(loc + 3));
    opc[4] = mon_get_mem_val(mem, (WORD)(loc + 4));

    dis_inst = mon_disassemble_to_string_internal(mem, loc, opc, hex_mode, opc_size, monitor_cpu_for_memspace[mem]);

    sprintf(buff, ".%s:%04x  %s", mon_memspace_string[mem], loc, dis_inst);

    return buff;
}
Example #19
0
static void set_addr_location(MON_ADDR *a, unsigned l)
{
    *a = new_addr(addr_memspace(*a), addr_mask(l));
}
Example #20
0
void mon_memory_display(int radix_type, MON_ADDR start_addr, MON_ADDR end_addr, mon_display_format_t format)
{
    unsigned int i, cnt = 0, len, max_width, real_width;
    WORD addr = 0;
    char printables[50];
    char prefix;
    MEMSPACE mem;
    WORD display_number;
    BYTE v;

    prefix = (format == DF_PETSCII) ? '>' : '*';

    if (radix_type) {
        if (radix_type != e_hexadecimal && radix_type != e_decimal && radix_type != e_octal) {
            max_width = (console_log->console_xres - 12)
                        / (radix_chars_per_byte[radix_type] + 2);
        } else {
            max_width = (4 * (console_log->console_xres - 12))
                        / (4 * (radix_chars_per_byte[radix_type] + 2) + 1);
        }

        max_width &= ~3;

        display_number = max_width * ((console_log->console_yres - 6) / 2);
    } else {
        max_width = 40;
        display_number = 128;
    }

    len = mon_evaluate_address_range(&start_addr, &end_addr, FALSE,
                                     display_number);
    mem = addr_memspace(start_addr);
    addr = addr_location(start_addr);

    while (cnt < len) {
        mon_out("%c%s:%04x ", prefix, mon_memspace_string[mem], addr);
        for (i = 0, real_width = 0; i < max_width; i++) {
            v = mon_get_mem_val(mem, (WORD)ADDR_LIMIT(addr + i));

            switch (radix_type) {
                case 0: /* special case == petscii text */
                    if (format == DF_PETSCII) {
                        mon_out("%c", charset_p_toascii(v, 1));
                    } else {
                        mon_out("%c", charset_p_toascii(
                                    charset_screencode_to_petcii(v), 1));
                    }
                    real_width++;
                    cnt++;
                    break;
                case e_decimal:
                    memset(printables, 0, 50);
                    if (!(cnt % 4)) {
                        mon_out(" ");
                    }
                    if (cnt < len) {
                        mon_out("%03d ", v);
                        real_width++;
                        cnt++;
                    } else {
                        mon_out("    ");
                    }
                    break;
                case e_hexadecimal:
                    memset(printables, 0, 50);
                    if (!(cnt % 4)) {
                        mon_out(" ");
                    }
                    if (cnt < len) {
                        mon_out("%02x ", v);
                        real_width++;
                    } else {
                        mon_out("   ");
                    }
                    cnt++;
                    break;
                case e_octal:
                    memset(printables, 0, 50);
                    if (!(cnt % 4)) {
                        mon_out(" ");
                    }
                    if (cnt < len) {
                        mon_out("%03o ", v);
                        real_width++;
                        cnt++;
                    } else {
                        mon_out("    ");
                    }
                    break;
                case e_binary:
                    memset(printables, 0, 50);
                    if (cnt < len) {
                        mon_print_bin(v, '1', '0');
                        mon_out(" ");
                        real_width++;
                        cnt++;
                    } else {
                        mon_out("         ");
                    }
                    break;
                default:
                    return;
            }
        }

        if (radix_type != 0) {
            memory_to_string(printables, mem, addr, real_width, FALSE);
            mon_out("  %s", printables);
        }
        mon_out("\n");
        addr = ADDR_LIMIT(addr + real_width);
        if (mon_stop_output != 0) {
            break;
        }
    }

    set_addr_location(&(dot_addr[mem]), addr);
}
static int mon_assemble_instr(const char *opcode_name, asm_mode_addr_info_t operand)
{
    WORD operand_value = operand.param;
    WORD operand_mode = operand.addr_mode;
    BYTE operand_extra_value = operand.addr_submode;
    BYTE i = 0, opcode = 0;
    int len, branch_offset;
    bool found = FALSE;
    MEMSPACE mem;
    WORD loc;

    mem = addr_memspace(asm_mode_addr);
    loc = addr_location(asm_mode_addr);

    do {
        const asm_opcode_info_t *opinfo;

        opinfo = (monitor_cpu_for_memspace[mem]->asm_opcode_info_get)(i, 0, 0);
        if (!strcasecmp(opinfo->mnemonic, opcode_name)) {
            /* Special case: ZERO PAGE RELATIVE mode needs special handling. */
            if (opinfo->addr_mode == ASM_ADDR_MODE_ZERO_PAGE_RELATIVE
                && operand_mode == ASM_ADDR_MODE_DOUBLE) {
                branch_offset = (operand_value - loc - 3) & 0xffff;
                if (branch_offset > 0x7f && branch_offset < 0xff80) {
                    mon_out("Branch offset too large.\n");
                    return -1;
                }
                operand_value = (operand_extra_value & 0xff) | ((branch_offset & 0xff) << 8);
                opcode = i;
                operand_mode = ASM_ADDR_MODE_ZERO_PAGE_RELATIVE;
                found = TRUE;
                break;
            }

            if (opinfo->addr_mode == operand_mode && found == FALSE) {
                opcode = i;
                found = TRUE;
                break;
            }

            /* Special case: Register A not specified for ACCUMULATOR mode. */
            if (operand_mode == ASM_ADDR_MODE_IMPLIED
                && opinfo->addr_mode == ASM_ADDR_MODE_ACCUMULATOR) {
                opcode = i;
                operand_mode = ASM_ADDR_MODE_ACCUMULATOR;
                found = TRUE;
                break;
            }

            /* Special case: RELATIVE mode looks like ZERO_PAGE or ABSOLUTE
               modes.  */
            if ((operand_mode == ASM_ADDR_MODE_ZERO_PAGE
                 || operand_mode == ASM_ADDR_MODE_ABSOLUTE)
                && opinfo->addr_mode == ASM_ADDR_MODE_RELATIVE) {
                branch_offset = (operand_value - loc - 2) & 0xffff;
                if (branch_offset > 0x7f && branch_offset < 0xff80) {
                    mon_out("Branch offset too large.\n");
                    return -1;
                }
                operand_value = (branch_offset & 0xff);
                operand_mode = ASM_ADDR_MODE_RELATIVE;
                opcode = i;
                found = TRUE;
                break;
            }

            /* Special case: opcode A - is A a register or $A? */
            /* If second case, is it zero page or absolute?  */
            if (operand_mode == ASM_ADDR_MODE_ACCUMULATOR
                && opinfo->addr_mode == ASM_ADDR_MODE_ZERO_PAGE) {
                opcode = i;
                operand_mode = ASM_ADDR_MODE_ZERO_PAGE;
                operand_value = 0x000a;
                found = TRUE;
                break;
            }

            /* It's safe to assume ABSOLUTE if ZERO_PAGE not yet found since
             * ZERO_PAGE versions always precede ABSOLUTE versions if they
             * exist.
             */
            if (operand_mode == ASM_ADDR_MODE_ACCUMULATOR
                && opinfo->addr_mode == ASM_ADDR_MODE_ABSOLUTE) {
                opcode = i;
                operand_mode = ASM_ADDR_MODE_ABSOLUTE;
                operand_value = 0x000a;
                found = TRUE;
                break;
            }

            /* It's safe to assume ABSOULTE if ZERO_PAGE not yet found since
             * ZERO_PAGE versions always precede ABSOLUTE versions if they
             * exist.
             */
            if (operand_mode == ASM_ADDR_MODE_ZERO_PAGE
                && opinfo->addr_mode == ASM_ADDR_MODE_ABSOLUTE) {
                opcode = i;
                operand_mode = ASM_ADDR_MODE_ABSOLUTE;
                found = TRUE;
                break;
            }
        }
        i++;
    } while (i != 0);

    if (!found) {
        mon_out("Instruction not valid.\n");
        return -1;
    }

    len = (monitor_cpu_for_memspace[mem]->asm_addr_mode_get_size)
              ((unsigned int)(operand_mode), 0, 0, 0);

    /* EP 98.08.23 use correct memspace for assembling.  */
    mon_set_mem_val(mem, loc, opcode);
    if (len >= 2) {
        mon_set_mem_val(mem, (WORD)(loc + 1), (BYTE)(operand_value & 0xff));
    }
    if (len >= 3) {
        mon_set_mem_val(mem, (WORD)(loc + 2),
                        (BYTE)((operand_value >> 8) & 0xff));
    }
static int mon_assemble_instr(const char *opcode_name, asm_mode_addr_info_t operand)
{
    WORD operand_value = operand.param;
    WORD operand_mode = operand.addr_mode;
    WORD operand_submode = operand.addr_submode;
    BYTE i = 0, j = 0, opcode = 0;
    int len, branch_offset;
    bool found = FALSE;
    MEMSPACE mem;
    WORD loc;
    int const prefix[3] = { -1, 0x10, 0x11 };
    BYTE opc[5];
    int opc_offset;
    int prefixlen;

    mem = addr_memspace(asm_mode_addr);
    loc = addr_location(asm_mode_addr);

    /*
     * Convert generic addressing modes to 6809 addressing modes.
     * The reason we have different numbers for them is that the disassembler
     * needs to skip prefix bytes in a 6809-specific manner.
     */
    switch (operand_mode) {
        case ASM_ADDR_MODE_IMMEDIATE:
            operand_mode = ASM_ADDR_MODE_IMM_BYTE;
            break;
        case ASM_ADDR_MODE_IMMEDIATE_16:
            operand_mode = ASM_ADDR_MODE_IMM_WORD;
            break;
        case ASM_ADDR_MODE_ZERO_PAGE:   /* we have no zero page */
            operand_mode = ASM_ADDR_MODE_EXTENDED;
            break;
        case ASM_ADDR_MODE_ABSOLUTE:
            operand_mode = ASM_ADDR_MODE_EXTENDED;
            break;
    }
    /*
     * Fix up another parsing ambiguity, for addr,X and addr,Y and addr,S.
     */
    if (operand_mode == ASM_ADDR_MODE_ZERO_PAGE_X ||
        operand_mode == ASM_ADDR_MODE_ABSOLUTE_X) {
        int reg = 0 << 5;
        operand_mode = ASM_ADDR_MODE_INDEXED;
        operand_submode = reg | make_offset_mode(operand_value);
    } else if (operand_mode == ASM_ADDR_MODE_ZERO_PAGE_Y ||
               operand_mode == ASM_ADDR_MODE_ABSOLUTE_Y) {
        int reg = 1 << 5;
        operand_mode = ASM_ADDR_MODE_INDEXED;
        operand_submode = reg | make_offset_mode(operand_value);
    } else if (operand_mode == ASM_ADDR_MODE_STACK_RELATIVE) {
        int reg = 3 << 5;
        operand_mode = ASM_ADDR_MODE_INDEXED;
        operand_submode = reg | make_offset_mode(operand_value);
    }

    DBG(printf("mon_assemble_instr: '%s' mode %d submode $%02x oper $%04x\n",
               opcode_name, operand_mode, operand_submode, operand_value));

    for (j = 0; j < 3 && !found; j++) {
        do {
            const asm_opcode_info_t *opinfo;

            if (prefix[j] == -1) {
                opinfo = (monitor_cpu_for_memspace[mem]->asm_opcode_info_get)(i, 0, 0);
                prefixlen = 0;
            } else {
                opinfo = (monitor_cpu_for_memspace[mem]->asm_opcode_info_get)(prefix[j], i, 0);
                prefixlen = 1;
            }

            if (!strcasecmp(opinfo->mnemonic, opcode_name)) {
                if (opinfo->addr_mode == operand_mode) {
                    opcode = i;
                    found = TRUE;
                    DBG(printf("found, prefix $%02x opcode $%02x\n", prefix[j], opcode));
                    break;
                }


                /* Special case: RELATIVE mode looks like EXTENDED mode.  */
                if (operand_mode == ASM_ADDR_MODE_EXTENDED
                    && opinfo->addr_mode == ASM_ADDR_MODE_REL_BYTE) {
                    branch_offset = operand_value - (loc + prefixlen + 2);
                    if (branch_offset > 127 || branch_offset < -128) {
                        mon_out("Branch offset too large.\n");
                        return -1;
                    }
                    operand_value = (branch_offset & 0xff);
                    operand_mode = ASM_ADDR_MODE_REL_BYTE;
                    opcode = i;
                    found = TRUE;
                    break;
                }

                /* Special case: RELATIVE mode looks like EXTENDED mode.  */
                if (operand_mode == ASM_ADDR_MODE_EXTENDED
                    && opinfo->addr_mode == ASM_ADDR_MODE_REL_WORD) {
                    branch_offset = operand_value - (loc + prefixlen + 3);
                    operand_value = (branch_offset & 0xffff);
                    operand_mode = ASM_ADDR_MODE_REL_WORD;
                    opcode = i;
                    found = TRUE;
                    break;
                }

#if 0
                /* Special case: opcode A - is A a register or $A? */
                /* If second case, is it zero page or absolute?  */
                if (operand_mode == ASM_ADDR_MODE_ACCUMULATOR
                    && opinfo->addr_mode == ASM_ADDR_MODE_ZERO_PAGE) {
                    opcode = i;
                    operand_mode = ASM_ADDR_MODE_ZERO_PAGE;
                    operand_value = 0x000a;
                    found = TRUE;
                    break;
                }
#endif
                /* If there is no operand and the opcode wants a register
                 * list, it could be an empty list.
                 */
                if (operand_mode == ASM_ADDR_MODE_IMPLIED
                    && (opinfo->addr_mode == ASM_ADDR_MODE_SYS_POST ||
                        opinfo->addr_mode == ASM_ADDR_MODE_USR_POST)) {
                    opcode = i;
                    operand_mode = opinfo->addr_mode;
                    operand_value = 0x00;
                    found = TRUE;
                    break;
                }
                /* If there are exactly 2 registers the parser thought it
                 * would be _REG_POST but it could also be a 2-item list.
                 * Fortunately it kept the other interpretation hidden away
                 * in the submode field.
                 */
                if (operand_mode == ASM_ADDR_MODE_REG_POST
                    && (opinfo->addr_mode == ASM_ADDR_MODE_SYS_POST ||
                        opinfo->addr_mode == ASM_ADDR_MODE_USR_POST)) {
                    opcode = i;
                    operand_mode = opinfo->addr_mode;
                    operand_value = operand_submode;
                    found = TRUE;
                    break;
                }
                /* The parser doesn't distinguish 2 kinds of register lists.
                 * Too bad if you write PSHS S or PSHU U.
                 */
                if (operand_mode == ASM_ADDR_MODE_SYS_POST
                    && opinfo->addr_mode == ASM_ADDR_MODE_USR_POST) {
                    opcode = i;
                    found = TRUE;
                    break;
                }
            }
            i++;
        }
        while (i != 0);
        if (found) {
            break;
        }
    }

    if (!found) {
        mon_out("Instruction not valid.\n");
        return -1;
    }

    opc_offset = 0;
    if (prefix[j] != -1) {
        opc[opc_offset++] = prefix[j];
    }
    opc[opc_offset++] = opcode;
    if (operand_mode == ASM_ADDR_MODE_INDEXED) {
        opc[opc_offset++] = (BYTE)operand_submode;
    }

    len = (monitor_cpu_for_memspace[mem]->asm_addr_mode_get_size)
              ((unsigned int)operand_mode, opc[0], opc[1], opc[2]);

    DBG(printf("len = %d\n", len));
    if (len == opc_offset + 1) {
        opc[opc_offset++] = operand_value & 0xFF;
    } else if (len == opc_offset + 2) {
        opc[opc_offset++] = operand_value >> 8;
        opc[opc_offset++] = operand_value & 0xFF;
    }
Example #23
0
void mon_drive_block_cmd(int op, int track, int sector, MON_ADDR addr)
{
    vdrive_t *vdrive;

    mon_evaluate_default_addr(&addr);

    vdrive = file_system_get_vdrive(8);

    if (!vdrive || vdrive->image == NULL) {
        mon_out("No disk attached\n");
        return;
    }

    if (!op) {
        BYTE readdata[256];
        int i, j, dst;
        MEMSPACE dest_mem;

        /* We ignore disk error codes here.  */
        if (vdrive_read_sector(vdrive, readdata, track, sector)
            < 0) {
            mon_out("Error reading track %d sector %d\n", track, sector);
            return;
        }

        if (mon_is_valid_addr(addr)) {
            dst = addr_location(addr);
            dest_mem = addr_memspace(addr);

            for (i = 0; i < 256; i++) {
                mon_set_mem_val(dest_mem, ADDR_LIMIT(dst + i), readdata[i]);
            }

            mon_out("Read track %d sector %d into address $%04x\n", track, sector, dst);
        } else {
            for (i = 0; i < 16; i++) {
                mon_out(">%04x", i * 16);
                for (j = 0; j < 16; j++) {
                    if ((j & 3) == 0) {
                        mon_out(" ");
                    }
                    mon_out(" %02x", readdata[i * 16 + j]);
                }
                mon_out("\n");
            }
        }
    } else {
        BYTE writedata[256];
        int i, src;
        MEMSPACE src_mem;

        src = addr_location(addr);
        src_mem = addr_memspace(addr);

        for (i = 0; i < 256; i++) {
            writedata[i] = mon_get_mem_val(src_mem, ADDR_LIMIT(src + i));
        }

        if (vdrive_write_sector(vdrive, writedata, track, sector)) {
            mon_out("Error writing track %d sector %d\n", track, sector);
            return;
        }

        mon_out("Write data from address $%04x to track %d sector %d\n",
                src, track, sector);
    }
}