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); }
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]); }
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; }
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; }
/* * 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; }