Пример #1
0
shpid_t lg_tag_indirect_h::_pid(uint4_t pid_num) const
{
    FUNC(lg_tag_indirect_h::_pid);

    // get the root page
    lpid_t root_pid(stid(), _iref.indirect_root);
    lgindex_p root;
    W_IGNORE( root.fix(root_pid, LATCH_SH) ); // PAGEFIXBUG
    if (!root.is_fixed()) return 0;

    // if the tree is only 1 level, return the correct pid easily
    if (indirect_type(_page_cnt) == t_large_1) {
        return root.pids(pid_num);
    }
    w_assert9(indirect_type(_page_cnt) == t_large_2);

    // find "slot" containing pointer to page with pid_num
    w_assert9( (pid_num/lgindex_p::max_pids) < max_uint2);
    slotid_t idx = (slotid_t)(pid_num/lgindex_p::max_pids);
    lpid_t indirect_pid(stid(), root.pids(idx));
    lgindex_p indirect;
    W_IGNORE( indirect.fix(indirect_pid, LATCH_SH) ); // PAGEFIXBUG
    if (!indirect.is_fixed()) return 0;

    return indirect.pids(pid_num % lgindex_p::max_pids);
}
Пример #2
0
shpid_t lg_tag_indirect_h::_last_indirect()  const
{
    FUNC(lg_tag_indirect_h::_last_indirect);
    if (indirect_type(_page_cnt) == t_large_1) {
        return _iref.indirect_root;
    }

    // read the root page
    lpid_t root_pid(stid(), _iref.indirect_root);
    lgindex_p root;
    W_IGNORE( root.fix(root_pid, LATCH_SH) ); // PAGEFIXBUG
    if (!root.is_fixed()) return 0; 
    
    shpid_t* pids = (shpid_t*)root.tuple_addr(0);
    w_assert9(pids);
    return(pids[(_page_cnt-1)/lgindex_p::max_pids]);
}
Пример #3
0
rc_t
lg_tag_indirect_h::_add_new_indirect(lpid_t& new_pid)
{
    FUNC(lg_tag_indirect_h::_add_new_indirect);
    // flags for new pages
    w_base_t::uint4_t flags = lgindex_p::t_virgin;

    if (indirect_type(_page_cnt) == t_large_1) {
        // must allocate a new root pid and point it to the current one
        lpid_t root_pid;
        W_DO(smlevel_0::io->alloc_a_page(stid(), 
                lpid_t::eof,  // near hint
                root_pid, // npages, array for output pids
                false, // not may_realloc 
                EX, // lock on pages
                false        // do not search file for free pages
                ));

        lgindex_p root;
        W_DO( root.fix(root_pid, LATCH_EX, flags) );
        w_assert1(root.is_fixed());
        W_DO(root.append(1, &_iref.indirect_root));
        w_assert9(root_pid.stid() == stid());
        _iref.indirect_root = root_pid.page;
    }

    // allocate a new page and point to it from the root
    W_DO(smlevel_0::io->alloc_a_page(stid(), 
                lpid_t::eof,  // near hint
                new_pid, // npages, array of output pids
                false,         // not may_realloc
                EX,        // lock on new pages
                false        // do not search file for free pages
                ));
    lgindex_p new_page;
    W_DO( new_page.fix(new_pid, LATCH_EX, flags) );  // format page

    lpid_t root_pid(stid(), _iref.indirect_root);
    lgindex_p root;
    W_DO( root.fix(root_pid, LATCH_EX) );
    w_assert1(root.is_fixed());
    W_DO(root.append(1, &new_pid.page));

    return RCOK;
}
Пример #4
0
static int
print_insn_rl78_common (bfd_vma addr, disassemble_info * dis, RL78_Dis_Isa isa)
{
    int rv;
    RL78_Data rl78_data;
    RL78_Opcode_Decoded opcode;
    const char * s;
#if DEBUG_SEMANTICS
    static char buf[200];
#endif

    rl78_data.pc = addr;
    rl78_data.dis = dis;

    rv = rl78_decode_opcode (addr, &opcode, rl78_get_byte, &rl78_data, isa);

    dis->bytes_per_line = 10;

#define PR (dis->fprintf_func)
#define PS (dis->stream)
#define PC(c) PR (PS, "%c", c)

    s = opcode.syntax;

#if DEBUG_SEMANTICS

    switch (opcode.id)
    {
    case RLO_unknown:
        s = "uknown";
        break;
    case RLO_add:
        s = "add: %e0%0 += %e1%1";
        break;
    case RLO_addc:
        s = "addc: %e0%0 += %e1%1 + CY";
        break;
    case RLO_and:
        s = "and: %e0%0 &= %e1%1";
        break;
    case RLO_branch:
        s = "branch: pc = %e0%0";
        break;
    case RLO_branch_cond:
        s = "branch_cond: pc = %e0%0 if %c1 / %e1%1";
        break;
    case RLO_branch_cond_clear:
        s = "branch_cond_clear: pc = %e0%0 if %c1 / %e1%1, %e1%1 = 0";
        break;
    case RLO_call:
        s = "call: pc = %e1%0";
        break;
    case RLO_cmp:
        s = "cmp: %e0%0 - %e1%1";
        break;
    case RLO_mov:
        s = "mov: %e0%0 = %e1%1";
        break;
    case RLO_or:
        s = "or: %e0%0 |= %e1%1";
        break;
    case RLO_rol:
        s = "rol: %e0%0 <<= %e1%1";
        break;
    case RLO_rolc:
        s = "rol: %e0%0 <<= %e1%1,CY";
        break;
    case RLO_ror:
        s = "ror: %e0%0 >>= %e1%1";
        break;
    case RLO_rorc:
        s = "ror: %e0%0 >>= %e1%1,CY";
        break;
    case RLO_sar:
        s = "sar: %e0%0 >>= %e1%1 signed";
        break;
    case RLO_sel:
        s = "sel: rb = %1";
        break;
    case RLO_shr:
        s = "shr: %e0%0 >>= %e1%1 unsigned";
        break;
    case RLO_shl:
        s = "shl: %e0%0 <<= %e1%1";
        break;
    case RLO_skip:
        s = "skip: if %c1";
        break;
    case RLO_sub:
        s = "sub: %e0%0 -= %e1%1";
        break;
    case RLO_subc:
        s = "subc: %e0%0 -= %e1%1 - CY";
        break;
    case RLO_xch:
        s = "xch: %e0%0 <-> %e1%1";
        break;
    case RLO_xor:
        s = "xor: %e0%0 ^= %e1%1";
        break;
    }

    sprintf(buf, "%s%%W%%f\t\033[32m%s\033[0m", s, opcode.syntax);
    s = buf;

#endif

    for (; *s; s++)
    {
        if (*s != '%')
        {
            PC (*s);
        }
        else
        {
            RL78_Opcode_Operand * oper;
            int do_hex = 0;
            int do_addr = 0;
            int do_es = 0;
            int do_sfr = 0;
            int do_cond = 0;
            int do_bang = 0;

            while (1)
            {
                s ++;
                switch (*s)
                {
                case 'x':
                    do_hex = 1;
                    break;
                case '!':
                    do_bang = 1;
                    break;
                case 'e':
                    do_es = 1;
                    break;
                case 'a':
                    do_addr = 1;
                    break;
                case 's':
                    do_sfr = 1;
                    break;
                case 'c':
                    do_cond = 1;
                    break;
                default:
                    goto no_more_modifiers;
                }
            }
no_more_modifiers:
            ;

            switch (*s)
            {
            case '%':
                PC ('%');
                break;

#if DEBUG_SEMANTICS

            case 'W':
                if (opcode.size == RL78_Word)
                    PR (PS, " \033[33mW\033[0m");
                break;

            case 'f':
                if (opcode.flags)
                {
                    char *comma = "";
                    PR (PS, "  \033[35m");

                    if (opcode.flags & RL78_PSW_Z)
                    {
                        PR (PS, "Z");
                        comma = ",";
                    }
                    if (opcode.flags & RL78_PSW_AC)
                    {
                        PR (PS, "%sAC", comma);
                        comma = ",";
                    }
                    if (opcode.flags & RL78_PSW_CY)
                    {
                        PR (PS, "%sCY", comma);
                        comma = ",";
                    }
                    PR (PS, "\033[0m");
                }
                break;

#endif

            case '0':
            case '1':
                oper = *s == '0' ? &opcode.op[0] : &opcode.op[1];
                if (do_es)
                {
                    if (oper->use_es && indirect_type (oper->type))
                        PR (PS, "es:");
                }

                if (do_bang)
                    PC ('!');

                if (do_cond)
                {
                    PR (PS, "%s", condition_names[oper->condition]);
                    break;
                }

                switch (oper->type)
                {
                case RL78_Operand_Immediate:
                    if (do_addr)
                        dis->print_address_func (oper->addend, dis);
                    else if (do_hex
                             || oper->addend > 999
                             || oper->addend < -999)
                        PR (PS, "%#x", oper->addend);
                    else
                        PR (PS, "%d", oper->addend);
                    break;

                case RL78_Operand_Register:
                    PR (PS, "%s", register_names[oper->reg]);
                    break;

                case RL78_Operand_Bit:
                    PR (PS, "%s.%d", register_names[oper->reg], oper->bit_number);
                    break;

                case RL78_Operand_Indirect:
                case RL78_Operand_BitIndirect:
                    switch (oper->reg)
                    {
                    case RL78_Reg_None:
                        if (oper->addend == 0xffffa && do_sfr && opcode.size == RL78_Byte)
                            PR (PS, "psw");
                        else if (oper->addend == 0xffff8 && do_sfr && opcode.size == RL78_Word)
                            PR (PS, "sp");
                        else if (oper->addend == 0xffff8 && do_sfr && opcode.size == RL78_Byte)
                            PR (PS, "spl");
                        else if (oper->addend == 0xffff9 && do_sfr && opcode.size == RL78_Byte)
                            PR (PS, "sph");
                        else if (oper->addend == 0xffffc && do_sfr && opcode.size == RL78_Byte)
                            PR (PS, "cs");
                        else if (oper->addend == 0xffffd && do_sfr && opcode.size == RL78_Byte)
                            PR (PS, "es");
                        else if (oper->addend == 0xffffe && do_sfr && opcode.size == RL78_Byte)
                            PR (PS, "pmc");
                        else if (oper->addend == 0xfffff && do_sfr && opcode.size == RL78_Byte)
                            PR (PS, "mem");
                        else if (oper->addend >= 0xffe20)
                            PR (PS, "%#x", oper->addend);
                        else
                        {
                            int faddr = oper->addend;
                            if (do_es && ! oper->use_es)
                                faddr += 0xf0000;
                            dis->print_address_func (faddr, dis);
                        }
                        break;

                    case RL78_Reg_B:
                    case RL78_Reg_C:
                    case RL78_Reg_BC:
                        PR (PS, "%d[%s]", oper->addend, register_names[oper->reg]);
                        break;

                    default:
                        PR (PS, "[%s", register_names[oper->reg]);
                        if (oper->reg2 != RL78_Reg_None)
                            PR (PS, "+%s", register_names[oper->reg2]);
                        if (oper->addend || do_addr)
                            PR (PS, "+%d", oper->addend);
                        PC (']');
                        break;

                    }
                    if (oper->type == RL78_Operand_BitIndirect)
                        PR (PS, ".%d", oper->bit_number);
                    break;

#if DEBUG_SEMANTICS
                /* Shouldn't happen - push and pop don't print
                   [SP] directly.  But we *do* use them for
                   semantic debugging.  */
                case RL78_Operand_PostInc:
                    PR (PS, "[%s++]", register_names[oper->reg]);
                    break;
                case RL78_Operand_PreDec:
                    PR (PS, "[--%s]", register_names[oper->reg]);
                    break;
#endif

                default:
                    /* If we ever print this, that means the
                       programmer tried to print an operand with a
                       type we don't expect.  Print the line and
                       operand number from rl78-decode.opc for
                       them.  */
                    PR (PS, "???%d.%d", opcode.lineno, *s - '0');
                    break;
                }
            }
        }
    }

#if DEBUG_SEMANTICS

    PR (PS, "\t\033[34m(line %d)\033[0m", opcode.lineno);

#endif

    return rv;
}
Пример #5
0
/* 
 * truncate() removes pages at the end of large records
 * implemented as indirect blocks 
 */
rc_t
lg_tag_indirect_h::truncate(uint4_t num_pages)
{
    FUNC(lg_tag_indirect_h::truncate);
    int         i;
    int         first_dealloc = (int)(_page_cnt-num_pages);
    int         last_dealloc = (int)(_page_cnt-1);
    recflags_t  rec_type = indirect_type(_page_cnt);

    for (i = first_dealloc; i <= last_dealloc; i++) {
        W_DO(smlevel_0::io->free_page(pid(i)));
    }

    int indirect_rm_count = 0;          // # indirect pages to remove
    int pids_rm_by_indirect = 0;  // # data pids removed
                                  // by removing indirect pages
    int pids_to_rm = 0;           // # of pids to rm from last indirect
 
    // indirect pages are only removed if t_large_2
    if (rec_type == t_large_2) {
        uint pids_on_last = _pages_on_last_indirect();
        if (pids_on_last > num_pages) {
            indirect_rm_count = 0;
        } else {
            indirect_rm_count = (num_pages-1)/lgindex_p::max_pids+1;
            pids_rm_by_indirect = pids_on_last+(indirect_rm_count-1)*lgindex_p::max_pids;
        }
    }
    pids_to_rm = num_pages-pids_rm_by_indirect;

    // remove any indirect pages we can
    if (indirect_rm_count > 0) {
        lpid_t        root_pid(stid(), _iref.indirect_root);
        lgindex_p root;
        W_DO( root.fix(root_pid, LATCH_EX) );
        w_assert1(root.is_fixed());

        // first deallocate the indirect pages
        w_assert9(root.pid_count() ==
                _page_cnt/lgindex_p::max_pids + 1);
        first_dealloc = root.pid_count()-indirect_rm_count;
        last_dealloc = root.pid_count()-1;
        for (i = first_dealloc; i <= last_dealloc; i++) {
            lpid_t pid_to_free(stid(), root.pids(i));
            W_DO(smlevel_0::io->free_page(pid_to_free));
        }

        // if will be only one indirect page left, then remember
        // the ID of this page
        /*
        shpid_t new_indirect_root;
        if (indirect_type(_page_cnt-num_pages) == t_large_1) { 
            new_indirect_root = root->pids(0);
        }
        */

        W_DO(root.truncate(indirect_rm_count));

        // if there is only one indirect page left, then switch to
        // a single level tree
        if (indirect_type(_page_cnt-num_pages) == t_large_1) { 
            w_assert9( ((_page_cnt-1)/lgindex_p::max_pids+1) -
                     indirect_rm_count == 0);
            if (root.pid_count() > 0) {
                // there is at least one page left in the record,
                // the the first page in the root becomes the new root
                _iref.indirect_root = root.pids(0);
            } else {
                // all pages have been removed, so there is no root
                _iref.indirect_root = 0;
            }
            root.unfix();
            W_DO(smlevel_0::io->free_page(root_pid));
        }
    }

    // if we have not removed all pages, we must truncate pids
    // from the last indirect page
    if (_page_cnt > num_pages) {

        // get the pid for the last indirect page before truncate point
        // temporarily lower _page_cnt
        _page_cnt -= num_pages;
        lpid_t last_index_pid(stid(), _last_indirect());
        _page_cnt += num_pages;

        lgindex_p last_index;
        W_DO( last_index.fix(last_index_pid, LATCH_EX) );
        w_assert1(last_index.is_fixed());
        W_DO(last_index.truncate(pids_to_rm));
    } else {
        w_assert9(_page_cnt == num_pages);
        // we have removed all data pages, so remove the root 
        // (assuming it is not 0 meaning it has already been removed)
        if (_iref.indirect_root != 0) {
            lpid_t root_pid(stid(), _iref.indirect_root);
            W_DO(smlevel_0::io->free_page(root_pid));
            _iref.indirect_root = 0;  // mark that there is no root
        }
    }
    return RCOK;
}