예제 #1
0
def mod(env, opinfo):
    a = to_signed_word(opinfo.operands[0])
    b = to_signed_word(opinfo.operands[1])
    result = abs(a) % abs(b)
    if a < 0: # spec says a determines sign
        result = -result
    set_var(env, opinfo.store_var, result)
예제 #2
0
def jg(env, opinfo):
    a = to_signed_word(opinfo.operands[0])
    b = to_signed_word(opinfo.operands[1])
    result = a > b

    if result == opinfo.branch_on:
        handle_branch(env, opinfo.branch_offset)
예제 #3
0
def mod(env, opinfo):
    a = to_signed_word(opinfo.operands[0])
    b = to_signed_word(opinfo.operands[1])
    result = abs(a) % abs(b)
    if a < 0:  # spec says a determines sign
        result = -result
    set_var(env, opinfo.store_var, result)
예제 #4
0
def set_cursor(env, opinfo):
    env.screen.finish_wrapping()

    try:
        row = to_signed_word(opinfo.operands[0])
        col = to_signed_word(opinfo.operands[1])
        if row < 1:  # why do we not error out here?
            row = 1
        if col < 1:  # same question
            col = 1

        # ignores win 0 (S 8.7.2.3)
        if env.current_window == 1:
            if col > env.hdr.screen_width_units:
                if DBG:
                    warn('set_cursor: set outside screen width', col)
                col = env.hdr.screen_width_units
            if row > env.hdr.screen_height_units:
                if DBG:
                    warn('set_cursor: set outside screen height', row)
                row = env.hdr.screen_height_units
            # see 3rd to last note at bottom of section 8
            env.top_window_height = max(env.top_window_height, row - 1)
            # fix that row,col have a 1,1 origin
            env.cursor[env.current_window] = row - 1, col - 1
    except Exception as e:
        warn("Exception during set_cursor:", e, repr(opinfo))
예제 #5
0
def jg(env, opinfo):
    a = to_signed_word(opinfo.operands[0])
    b = to_signed_word(opinfo.operands[1])
    result = a > b

    if result == opinfo.branch_on:
        handle_branch(env, opinfo.branch_offset)
예제 #6
0
def div(env, opinfo):
    a = to_signed_word(opinfo.operands[0])
    b = to_signed_word(opinfo.operands[1])
    num_neg = (a < 0) + (b < 0)
    result = abs(a) // abs(b)
    if num_neg == 1:
        result = -result
    set_var(env, opinfo.store_var, result)
예제 #7
0
def art_shift(env, opinfo):
    number = to_signed_word(opinfo.operands[0])
    places = to_signed_word(opinfo.operands[1])
    if places < 0:
        result = number >> abs(places)
    else:
        result = number << places
    set_var(env, opinfo.store_var, result)
예제 #8
0
def div(env, opinfo):
    a = to_signed_word(opinfo.operands[0])
    b = to_signed_word(opinfo.operands[1])
    num_neg = (a < 0) + (b < 0)
    result = abs(a) // abs(b)
    if num_neg == 1:
        result = -result
    set_var(env, opinfo.store_var, result)
예제 #9
0
def art_shift(env, opinfo):
    number = to_signed_word(opinfo.operands[0])
    places = to_signed_word(opinfo.operands[1])
    if places < 0:
        result = number >> abs(places)
    else:
        result = number << places
    set_var(env, opinfo.store_var, result)
예제 #10
0
def dec_chk(env, opinfo):
    var_loc = opinfo.operands[0]
    chk_val = to_signed_word(opinfo.operands[1])

    var_val = to_signed_word(get_var(env, var_loc) - 1)
    set_var(env, var_loc, var_val)

    result = var_val < chk_val
    if result == opinfo.branch_on:
        handle_branch(env, opinfo.branch_offset)
예제 #11
0
def dec_chk(env, opinfo):
    var_loc = opinfo.operands[0]
    chk_val = to_signed_word(opinfo.operands[1])

    var_val = to_signed_word(get_var(env, var_loc) - 1)
    set_var(env, var_loc, var_val)

    result = var_val < chk_val
    if result == opinfo.branch_on:
        handle_branch(env, opinfo.branch_offset)
예제 #12
0
def storew(env, opinfo):
    array_addr = opinfo.operands[0]
    word_index = to_signed_word(opinfo.operands[1])
    val = opinfo.operands[2]
    word_loc = 0xffff & (array_addr + 2*word_index)

    env.write16(word_loc, val)
예제 #13
0
def storeb(env, opinfo):
    array_addr = opinfo.operands[0]
    byte_index = to_signed_word(opinfo.operands[1])
    val = opinfo.operands[2] & 0xff
    mem_loc = 0xffff & (array_addr + byte_index)

    env.write8(mem_loc, val)
예제 #14
0
def dbg_decode_result(env, opname, store_var):
    if 'call' in opname:
        return 'unknown (just called)'
    var = ops.get_var(env, store_var, pop_stack=False)
    if opname in ['add', 'sub', 'mul', 'div', 'mod']:
        return to_signed_word(var)
    return var
예제 #15
0
def dbg_decode_result(env, opname, store_var):
    if 'call' in opname:
        return 'unknown (just called)'
    var = ops.get_var(env, store_var, pop_stack=False)
    if opname in ['add', 'sub', 'mul', 'div', 'mod']:
        return to_signed_word(var)
    return var
예제 #16
0
def storew(env, opinfo):
    array_addr = opinfo.operands[0]
    word_index = to_signed_word(opinfo.operands[1])
    val = opinfo.operands[2]
    word_loc = 0xffff & (array_addr + 2 * word_index)

    env.write16(word_loc, val)
예제 #17
0
def storeb(env, opinfo):
    array_addr = opinfo.operands[0]
    byte_index = to_signed_word(opinfo.operands[1])
    val = opinfo.operands[2] & 0xff
    mem_loc = 0xffff & (array_addr + byte_index)

    env.write8(mem_loc, val)
예제 #18
0
def random_(env, opinfo):
    rand_max = to_signed_word(opinfo.operands[0])
    if rand_max < 0:
        random.seed(rand_max)
        result = 0
    elif rand_max == 0:
        random.seed()
        result = 0
    else:
        result = random.randint(1, rand_max)
    set_var(env, opinfo.store_var, result)
예제 #19
0
def dbg_decode_operands(env, opname, operands):
    if opname in ['add', 'sub', 'mul', 'div', 'mod', 'jump', 'random_', 'print_num']:
        return map(to_signed_word, operands)
    elif opname in ['loadw', 'loadb', 'storew', 'storeb', 'inc_chk', 'dec_chk']:
        return [operands[0], to_signed_word(operands[1])] + operands[2:]
    elif opname in ['print_', 'print_ret']:
        result = ops.unpack_string(env, operands)
        if len(result) > 40:
            return repr(result[:40] + '...')
        return result
    return operands
예제 #20
0
def random_(env, opinfo):
    rand_max = to_signed_word(opinfo.operands[0])
    if rand_max < 0:
        random.seed(rand_max)
        result = 0
    elif rand_max == 0:
        random.seed()
        result = 0
    else:
        result = random.randint(1, rand_max)
    set_var(env, opinfo.store_var, result)
예제 #21
0
def set_cursor(env, opinfo):
    env.screen.finish_wrapping()

    row = to_signed_word(opinfo.operands[0])
    col = to_signed_word(opinfo.operands[1])
    if row < 1: # why do we not error out here?
        row = 1
    if col < 1: # same question
        col = 1

    # ignores win 0 (S 8.7.2.3)
    if env.current_window == 1:
        if col > env.hdr.screen_width_units:
            if DBG:
                warn('set_cursor: set outside screen width', col)
            col = env.hdr.screen_width_units
        if row > env.hdr.screen_height_units:
            if DBG:
                warn('set_cursor: set outside screen height', row)
            row = env.hdr.screen_height_units
        # see 3rd to last note at bottom of section 8
        env.top_window_height = max(env.top_window_height, row-1)
        # fix that row,col have a 1,1 origin
        env.cursor[env.current_window] = row-1, col-1
예제 #22
0
def dbg_decode_operands(env, opname, operands):
    if opname in [
            'add', 'sub', 'mul', 'div', 'mod', 'jump', 'random_', 'print_num'
    ]:
        return map(to_signed_word, operands)
    elif opname in [
            'loadw', 'loadb', 'storew', 'storeb', 'inc_chk', 'dec_chk'
    ]:
        return [operands[0], to_signed_word(operands[1])] + operands[2:]
    elif opname in ['print_', 'print_ret']:
        result = ops.unpack_string(env, operands)
        if len(result) > 40:
            return repr(result[:40] + '...')
        return result
    return operands
예제 #23
0
def erase_window(env, opinfo):
    env.screen.finish_wrapping()

    window = to_signed_word(opinfo.operands[0])

    if window in [0, -1, -2]:
        env.screen.blank_bottom_win()
    if window in [1, -1, -2]:
        env.screen.blank_top_win()

    if window == -1:
        env.top_window_height = 0
        env.current_window = 0

    if window in [0, -1, -2]:
        env.cursor[0] = get_cursor_loc_after_erase(env, 0)
    if window in [1, -1, -2]:
        env.cursor[1] = get_cursor_loc_after_erase(env, 1)
예제 #24
0
def erase_window(env, opinfo):
    env.screen.finish_wrapping()

    window = to_signed_word(opinfo.operands[0])

    if window in [0, -1, -2]:
        env.screen.blank_bottom_win()
    if window in [1, -1, -2]:
        env.screen.blank_top_win()

    if window == -1:
        env.top_window_height = 0
        env.current_window = 0

    if window in [0, -1, -2]:
        env.cursor[0] = get_cursor_loc_after_erase(env, 0)
    if window in [1, -1, -2]:
        env.cursor[1] = get_cursor_loc_after_erase(env, 1)
예제 #25
0
def copy_table(env, opinfo):
    first = opinfo.operands[0]
    second = opinfo.operands[1]
    size = to_signed_word(opinfo.operands[2])
    if second == 0:
        # zeros out first
        size = abs(size)
        for i in range(size):
            env.write8(first+i, 0)
    elif size > 0:
        # protects against corruption of overlapping tables
        tab = env.mem[first:first+size]
        for i in range(size):
            env.write8(second+i, tab[i])
    elif size < 0:
        # allows for the corruption of overlapping tables
        size = abs(size)
        for i in range(size):
            env.write8(second+i, env.mem[first+i])
예제 #26
0
def copy_table(env, opinfo):
    first = opinfo.operands[0]
    second = opinfo.operands[1]
    size = to_signed_word(opinfo.operands[2])
    if second == 0:
        # zeros out first
        size = abs(size)
        for i in range(size):
            env.write8(first + i, 0)
    elif size > 0:
        # protects against corruption of overlapping tables
        tab = env.mem[first:first + size]
        for i in range(size):
            env.write8(second + i, tab[i])
    elif size < 0:
        # allows for the corruption of overlapping tables
        size = abs(size)
        for i in range(size):
            env.write8(second + i, env.mem[first + i])
예제 #27
0
def output_stream(env, opinfo):
    stream = to_signed_word(opinfo.operands[0])
    if stream < 0:
        stream = abs(stream)
        if stream == 3:
            table_addr = env.memory_ostream_stack.pop()
            zscii_buffer = ascii_to_zscii(env.output_buffer[stream])
            buflen = len(zscii_buffer)
            env.write16(table_addr, buflen)
            for i in range(len(zscii_buffer)):
                env.write8(table_addr+2+i, zscii_buffer[i])
            env.output_buffer[stream] = ''
            if len(env.memory_ostream_stack) == 0:
                env.selected_ostreams.discard(stream)
        else:
            env.selected_ostreams.discard(stream)
    elif stream > 0:
        env.selected_ostreams.add(stream)
        if stream == 3:
            table_addr = opinfo.operands[1]
            if len(env.memory_ostream_stack) == 16:
                err('too many memory-based ostreams (>16)')
            env.memory_ostream_stack.append(table_addr)
예제 #28
0
def output_stream(env, opinfo):
    stream = to_signed_word(opinfo.operands[0])
    if stream < 0:
        stream = abs(stream)
        if stream == 3:
            table_addr = env.memory_ostream_stack.pop()
            zscii_buffer = ascii_to_zscii(env.output_buffer[stream])
            buflen = len(zscii_buffer)
            env.write16(table_addr, buflen)
            for i in range(len(zscii_buffer)):
                env.write8(table_addr + 2 + i, zscii_buffer[i])
            env.output_buffer[stream] = ''
            if len(env.memory_ostream_stack) == 0:
                env.selected_ostreams.discard(stream)
        else:
            env.selected_ostreams.discard(stream)
    elif stream > 0:
        env.selected_ostreams.add(stream)
        if stream == 3:
            table_addr = opinfo.operands[1]
            if len(env.memory_ostream_stack) == 16:
                err('too many memory-based ostreams (>16)')
            env.memory_ostream_stack.append(table_addr)
예제 #29
0
def loadw(env, opinfo):
    array_addr = opinfo.operands[0]
    word_index = to_signed_word(opinfo.operands[1])
    word_loc = 0xffff & (array_addr + 2 * word_index)

    set_var(env, opinfo.store_var, env.u16(word_loc))
예제 #30
0
def decode(env, pc):

    opcode = env.mem[pc]
    form = get_opcode_form(env, opcode)
    count = get_operand_count(opcode, form)

    if form == ExtForm:
        opcode = env.mem[pc+1]

    if form == ShortForm:
        szbyte = (opcode >> 4) & 3
        szbyte = (szbyte << 6) | 0x3f
        operand_ptr = pc+1
        sizes = get_operand_sizes(szbyte)
    elif form == VarForm:
        szbyte = env.mem[pc+1]
        operand_ptr = pc+2
        sizes = get_operand_sizes(szbyte)
        # handle call_vn2/vs2's extra szbyte
        if opcode in (236, 250):
            szbyte2 = env.mem[pc+2]
            sizes += get_operand_sizes(szbyte2)
            operand_ptr = pc+3
    elif form == ExtForm:
        szbyte = env.mem[pc+2]
        operand_ptr = pc+3
        sizes = get_operand_sizes(szbyte)
    elif form == LongForm:
        operand_ptr = pc+1
        sizes = []
        for offset in (6,5):
            if (opcode >> offset) & 1:
                sizes.append(VarSize)
            else:
                sizes.append(ByteSize)
    else:
        err('unknown opform specified: ' + str(form))

    operands = []
    var_op_info = []
    for i in range(len(sizes)):
        size = sizes[i]
        if size == WordSize:
            operands.append(env.u16(operand_ptr))
            operand_ptr += 2
        elif size == ByteSize:
            operands.append(env.mem[operand_ptr])
            operand_ptr += 1
        elif size == VarSize:
            operands.append(None) #this is fixedup after every load from icache
            var_num = env.mem[operand_ptr]
            var_op_info.append( (i,var_num) )
            operand_ptr += 1
        else:
            err('unknown operand size specified: ' + str(size))

    if form == ExtForm:
        dispatch = ops.ext_dispatch
        has_store_var = ops.ext_has_store_var
        has_branch_var = ops.ext_has_branch_var
    else:
        dispatch = ops.dispatch
        has_store_var = ops.has_store_var
        has_branch_var = ops.has_branch_var

    opinfo = OpInfo(operands, var_op_info)

    opinfo.opcode = opcode
    opinfo.is_extended = form == ExtForm

    if has_store_var[opcode]:
        opinfo.store_var = env.mem[operand_ptr]
        opinfo.last_pc_store_var = operand_ptr # to make quetzal saves easier
        operand_ptr += 1

    if has_branch_var[opcode]: # std:4.7
        branch_info = env.mem[operand_ptr]
        opinfo.last_pc_branch_var = operand_ptr # to make quetzal saves easier
        operand_ptr += 1
        opinfo.branch_on = (branch_info & 128) == 128
        if branch_info & 64:
            opinfo.branch_offset = branch_info & 0x3f
        else:
            branch_offset = branch_info & 0x3f
            branch_offset <<= 8
            branch_offset |= env.mem[operand_ptr]
            operand_ptr += 1
            # sign extend 14b # to 16b
            if branch_offset & 0x2000:
                branch_offset |= 0xc000
            opinfo.branch_offset = to_signed_word(branch_offset)

    # handle print_ and print_ret's string operand
    if form != ExtForm and opcode in (178, 179):
        while True:
            word = env.u16(operand_ptr)
            operand_ptr += 2
            operands.append(word)
            if word & 0x8000:
                break

    # After all that, operand_ptr should point to the next opcode
    next_pc = operand_ptr

    if DBG:
        def hex_out(bytes):
            s = ''
            for b in bytes:
                s += hex(b) + ' '
            return s
        op_hex = hex_out(env.mem[pc:next_pc])

        warn('decode: pc', hex(pc))
        warn('      opcode', opcode)
        warn('      form', form)
        warn('      count', count)
        if opinfo.store_var:
            warn('      store_var', ops.get_var_name(opinfo.store_var))
        warn('      sizes', sizes)
        warn('      operands', opinfo.operands)
        warn('      next_pc', hex(next_pc))
        #warn('      bytes', op_hex)

    return dispatch[opcode], opinfo, next_pc
예제 #31
0
def decode(env, pc):

    opcode = env.mem[pc]
    form = get_opcode_form(env, opcode)
    count = get_operand_count(opcode, form)

    if form == ExtForm:
        opcode = env.mem[pc + 1]

    if form == ShortForm:
        szbyte = (opcode >> 4) & 3
        szbyte = (szbyte << 6) | 0x3f
        operand_ptr = pc + 1
        sizes = get_operand_sizes(szbyte)
    elif form == VarForm:
        szbyte = env.mem[pc + 1]
        operand_ptr = pc + 2
        sizes = get_operand_sizes(szbyte)
        # handle call_vn2/vs2's extra szbyte
        if opcode in (236, 250):
            szbyte2 = env.mem[pc + 2]
            sizes += get_operand_sizes(szbyte2)
            operand_ptr = pc + 3
    elif form == ExtForm:
        szbyte = env.mem[pc + 2]
        operand_ptr = pc + 3
        sizes = get_operand_sizes(szbyte)
    elif form == LongForm:
        operand_ptr = pc + 1
        sizes = []
        for offset in (6, 5):
            if (opcode >> offset) & 1:
                sizes.append(VarSize)
            else:
                sizes.append(ByteSize)
    else:
        err('unknown opform specified: ' + str(form))

    operands = []
    var_op_info = []
    for i in range(len(sizes)):
        size = sizes[i]
        if size == WordSize:
            operands.append(env.u16(operand_ptr))
            operand_ptr += 2
        elif size == ByteSize:
            operands.append(env.mem[operand_ptr])
            operand_ptr += 1
        elif size == VarSize:
            operands.append(
                None)  #this is fixedup after every load from icache
            var_num = env.mem[operand_ptr]
            var_op_info.append((i, var_num))
            operand_ptr += 1
        else:
            err('unknown operand size specified: ' + str(size))

    if form == ExtForm:
        dispatch = ops.ext_dispatch
        has_store_var = ops.ext_has_store_var
        has_branch_var = ops.ext_has_branch_var
    else:
        dispatch = ops.dispatch
        has_store_var = ops.has_store_var
        has_branch_var = ops.has_branch_var

    opinfo = OpInfo(operands, var_op_info)

    opinfo.opcode = opcode
    opinfo.is_extended = form == ExtForm

    if has_store_var[opcode]:
        opinfo.store_var = env.mem[operand_ptr]
        opinfo.last_pc_store_var = operand_ptr  # to make quetzal saves easier
        operand_ptr += 1

    if has_branch_var[opcode]:  # std:4.7
        branch_info = env.mem[operand_ptr]
        opinfo.last_pc_branch_var = operand_ptr  # to make quetzal saves easier
        operand_ptr += 1
        opinfo.branch_on = (branch_info & 128) == 128
        if branch_info & 64:
            opinfo.branch_offset = branch_info & 0x3f
        else:
            branch_offset = branch_info & 0x3f
            branch_offset <<= 8
            branch_offset |= env.mem[operand_ptr]
            operand_ptr += 1
            # sign extend 14b # to 16b
            if branch_offset & 0x2000:
                branch_offset |= 0xc000
            opinfo.branch_offset = to_signed_word(branch_offset)

    # handle print_ and print_ret's string operand
    if form != ExtForm and opcode in (178, 179):
        while True:
            word = env.u16(operand_ptr)
            operand_ptr += 2
            operands.append(word)
            if word & 0x8000:
                break

    # After all that, operand_ptr should point to the next opcode
    next_pc = operand_ptr

    if DBG:

        def hex_out(bytes):
            s = ''
            for b in bytes:
                s += hex(b) + ' '
            return s

        op_hex = hex_out(env.mem[pc:next_pc])

        warn('decode: pc', hex(pc))
        warn('      opcode', opcode)
        warn('      form', form)
        warn('      count', count)
        if opinfo.store_var:
            warn('      store_var', ops.get_var_name(opinfo.store_var))
        warn('      sizes', sizes)
        warn('      operands', opinfo.operands)
        warn('      next_pc', hex(next_pc))
        #warn('      bytes', op_hex)

    return dispatch[opcode], opinfo, next_pc
예제 #32
0
def mul(env, opinfo):
    a = to_signed_word(opinfo.operands[0])
    b = to_signed_word(opinfo.operands[1])
    result = a * b
    set_var(env, opinfo.store_var, result)
예제 #33
0
def print_num(env, opinfo):
    num = to_signed_word(opinfo.operands[0])
    write(env, str(num))
예제 #34
0
def mul(env, opinfo):
    a = to_signed_word(opinfo.operands[0])
    b = to_signed_word(opinfo.operands[1])
    result = a*b
    set_var(env, opinfo.store_var, result)
예제 #35
0
def dec(env, opinfo):
    var_num = opinfo.operands[0]
    var_val = to_signed_word(get_var(env, var_num))
    set_var(env, var_num, var_val-1)
예제 #36
0
def dec(env, opinfo):
    var_num = opinfo.operands[0]
    var_val = to_signed_word(get_var(env, var_num))
    set_var(env, var_num, var_val - 1)
예제 #37
0
def loadb(env, opinfo):
    array_addr = opinfo.operands[0]
    byte_index = to_signed_word(opinfo.operands[1])
    byte_loc = 0xffff & (array_addr + byte_index)

    set_var(env, opinfo.store_var, env.mem[byte_loc]) 
예제 #38
0
def loadw(env, opinfo):
    array_addr = opinfo.operands[0]
    word_index = to_signed_word(opinfo.operands[1])
    word_loc = 0xffff & (array_addr + 2*word_index)

    set_var(env, opinfo.store_var, env.u16(word_loc))
예제 #39
0
def jump(env, opinfo):
    offset = to_signed_word(opinfo.operands[0])
    env.pc += offset - 2
예제 #40
0
def jump(env, opinfo):
    offset = to_signed_word(opinfo.operands[0])
    env.pc += offset - 2
예제 #41
0
def loadb(env, opinfo):
    array_addr = opinfo.operands[0]
    byte_index = to_signed_word(opinfo.operands[1])
    byte_loc = 0xffff & (array_addr + byte_index)

    set_var(env, opinfo.store_var, env.mem[byte_loc])
예제 #42
0
def print_num(env, opinfo):
    num = to_signed_word(opinfo.operands[0])
    write(env, str(num))