static int patch_feature_section(unsigned long value, struct fixup_entry *fcur)
{
	unsigned int *start, *end, *alt_start, *alt_end, *src, *dest;

	start = calc_addr(fcur, fcur->start_off);
	end = calc_addr(fcur, fcur->end_off);
	alt_start = calc_addr(fcur, fcur->alt_start_off);
	alt_end = calc_addr(fcur, fcur->alt_end_off);

	if ((alt_end - alt_start) > (end - start))
		return 1;

	if ((value & fcur->mask) == fcur->value)
		return 0;

	src = alt_start;
	dest = start;

	for (; src < alt_end; src++, dest++) {
		if (patch_alt_instruction(src, dest, alt_start, alt_end))
			return 1;
	}

	for (; dest < end; dest++)
		patch_instruction(dest, PPC_INST_NOP);

	return 0;
}
Ejemplo n.º 2
0
static void internal_blk0_store(WORD addr, BYTE value, WORD base, int ro)
{
    BYTE mode;
    int bank;
    unsigned int faddr;

    mode = register_a & REGA_MODE_MASK;

    /* Blk0 is hardwired to bank 0 */
    bank = 0;

    /* Calculate Address */
    faddr = calc_addr(addr, bank, base);

    /* Perform access */
    switch (mode) {
        case MODE_ROM_RAM:
        case MODE_RAM1:
        case MODE_RAM2:
            if (!ro) {
                cart_ram[faddr] = value;
            }
            break;
        case MODE_SUPER_ROM:
        case MODE_SUPER_RAM:
            cart_ram[faddr] = value;
            break;
        default:
            break;
    }
}
Ejemplo n.º 3
0
/*
 *   Reset 
 */
void CTcDataStream::reset()
{
    /* move the write pointer back to the start */
    ofs_ = 0;
    obj_file_start_ofs_ = 0;

    /* back to the first page */
    page_cur_ = 0;

    /* set up to write to the first page, if we have any pages at all */
    if (pages_ != 0)
    {
        /* we have all of the first page available again */
        wp_ = calc_addr(0);
        rem_ = TCCS_PAGE_SIZE;
    }

    /* reset the allocator */
    allocator_->reset();

    /* 
     *   forget all of the anchors (no need to delete them explicitly -
     *   they were allocated from our allocator pool, which we've reset to
     *   completely discard everything it contained)
     */
    first_anchor_ = last_anchor_ = 0;
}
Ejemplo n.º 4
0
/*
 *   Get a pointer to a block at a given offset and a given length.  
 */
const char *CTcDataStream::get_block_ptr(ulong ofs,
                                         ulong requested_len,
                                         ulong *available_len)
{
    size_t page_rem;

    /* 
     *   determine how much is left on the page containing the offset
     *   after the given offset 
     */
    page_rem = TCCS_PAGE_SIZE - (ofs % TCCS_PAGE_SIZE);

    /* 
     *   if the amount remaining on the page is greater than the request
     *   length, the available length is the entire request; otherwise,
     *   the available length is the amount remaining on the page 
     */
    if (page_rem >= requested_len)
        *available_len = requested_len;
    else
        *available_len = page_rem;

    /* return the address at this offset */
    return calc_addr(ofs);
}
Ejemplo n.º 5
0
/*
 *   Copy a chunk of the stream to the given buffer 
 */
void CTcDataStream::copy_to_buf(char *buf, ulong start_ofs, ulong len)
{
    /* read the data from each page that the block spans */
    while (len != 0)
    {
        size_t cur;
        
        /* 
         *   determine how much is left on the page containing the current
         *   starting offset 
         */
        cur = TCCS_PAGE_SIZE - (start_ofs % TCCS_PAGE_SIZE);
        
        /* 
         *   figure out how much we can copy - copy the whole remaining
         *   size, but no more than the amount remaining on this page 
         */
        if (cur > len)
            cur = (size_t)len;

        /* copy the data */
        memcpy(buf, calc_addr(start_ofs), cur);

        /* advance past this chunk */
        len -= cur;
        start_ofs += cur;
        buf += cur;
    }
}
Ejemplo n.º 6
0
static BYTE internal_blk0_read(WORD addr, WORD base)
{
    BYTE mode;
    int bank;
    unsigned int faddr;
    BYTE value;

    mode = register_a & REGA_MODE_MASK;

    /* Blk0 is hardwired to bank 0 */
    bank = 0;

    /* Calculate Address */
    faddr = calc_addr(addr, bank, base);

    /* Perform access */
    switch (mode) {
        case MODE_ROM_RAM:
        case MODE_RAM1:
        case MODE_RAM2:
        case MODE_SUPER_ROM:
        case MODE_SUPER_RAM:
            value = cart_ram[faddr];
            break;
        default:
            value = vic20_cpu_last_data;
            break;
    }
    return value;
}
Ejemplo n.º 7
0
/*
 * docmdline() - handle a colon command
 *
 * Handles a colon command received interactively by getcmdln() or from
 * the environment variable "BVIINIT" (or eventually .bvirc).
 */
void docmdline(char *cmdline)
{
    char buff[CMDSZ];
    char cmdbuf[CMDSZ];
    char cmdname[MAXNAME];
    char *cmd;
    char *p;
    size_t len;
    int n, ok, ret;
    int force = 0;
    int saveflag;
    if(*cmdline == '\0') {
        return;
    }
    if(*cmdline == '"') {
        return;    /** comment **/
    }
    if(strlen(cmdline) > CMDSZ - 2) {
        emsg("Command too long");
        return;
    }
    strcpy(buff, cmdline);
    cmd = buff;
    /* With no address given, we start at the beginning of the file and
     * go to the end of the file (not line like in vi).
     */
    addr_flag = 0;
    start_addr = mem;
    end_addr = maxpos - 1;
    SKIP_WHITE
    if(*cmd == '%') {
        cmd++;
        addr_flag = 2;
    } else {
        if((start_addr = calc_addr(&cmd, mem)) == NULL) {
            return;
        }
        if(*cmd == ',') {
            cmd++;
            addr_flag = 1;
            SKIP_WHITE
            if((end_addr = calc_addr(&cmd, maxpos - 1)) == NULL) {
                return;
            }
        } else {
            if(addr_flag) {
void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end)
{
	struct fixup_entry *fcur, *fend;

	fcur = fixup_start;
	fend = fixup_end;

	for (; fcur < fend; fcur++) {
		if (patch_feature_section(value, fcur)) {
			WARN_ON(1);
			printk("Unable to patch feature section at %p - %p" \
				" with %p - %p\n",
				calc_addr(fcur, fcur->start_off),
				calc_addr(fcur, fcur->end_off),
				calc_addr(fcur, fcur->alt_start_off),
				calc_addr(fcur, fcur->alt_end_off));
		}
	}
}
Ejemplo n.º 9
0
void
vl_idct_stage2_vert_shader(struct vl_idct *idct, struct ureg_program *shader,
                           unsigned first_output, struct ureg_dst tex)
{
    struct ureg_src vrect, vpos;
    struct ureg_src scale;
    struct ureg_dst t_start;
    struct ureg_dst o_l_addr[2], o_r_addr[2];

    vrect = ureg_DECL_vs_input(shader, VS_I_RECT);
    vpos = ureg_DECL_vs_input(shader, VS_I_VPOS);

    t_start = ureg_DECL_temporary(shader);

    --first_output;

    o_l_addr[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, first_output + VS_O_L_ADDR0);
    o_l_addr[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, first_output + VS_O_L_ADDR1);

    o_r_addr[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, first_output + VS_O_R_ADDR0);
    o_r_addr[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, first_output + VS_O_R_ADDR1);

    scale = ureg_imm2f(shader,
                       (float)VL_BLOCK_WIDTH / idct->buffer_width,
                       (float)VL_BLOCK_HEIGHT / idct->buffer_height);

    ureg_MUL(shader, ureg_writemask(tex, TGSI_WRITEMASK_Z),
             ureg_scalar(vrect, TGSI_SWIZZLE_X),
             ureg_imm1f(shader, VL_BLOCK_WIDTH / idct->nr_of_render_targets));
    ureg_MUL(shader, ureg_writemask(t_start, TGSI_WRITEMASK_XY), vpos, scale);

    calc_addr(shader, o_l_addr, vrect, ureg_imm1f(shader, 0.0f), false, false, VL_BLOCK_WIDTH / 4);
    calc_addr(shader, o_r_addr, ureg_src(tex), ureg_src(t_start), true, false, idct->buffer_height / 4);

    ureg_MOV(shader, ureg_writemask(o_r_addr[0], TGSI_WRITEMASK_Z), ureg_src(tex));
    ureg_MOV(shader, ureg_writemask(o_r_addr[1], TGSI_WRITEMASK_Z), ureg_src(tex));
}
Ejemplo n.º 10
0
static void *
create_mismatch_vert_shader(struct vl_idct *idct)
{
    struct ureg_program *shader;
    struct ureg_src vpos;
    struct ureg_src scale;
    struct ureg_dst t_tex;
    struct ureg_dst o_vpos, o_addr[2];

    shader = ureg_create(TGSI_PROCESSOR_VERTEX);
    if (!shader)
        return NULL;

    vpos = ureg_DECL_vs_input(shader, VS_I_VPOS);

    t_tex = ureg_DECL_temporary(shader);

    o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS);

    o_addr[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR0);
    o_addr[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR1);

    /*
     * scale = (VL_BLOCK_WIDTH, VL_BLOCK_HEIGHT) / (dst.width, dst.height)
     *
     * t_vpos = vpos + 7 / VL_BLOCK_WIDTH
     * o_vpos.xy = t_vpos * scale
     *
     * o_addr = calc_addr(...)
     *
     */

    scale = ureg_imm2f(shader,
                       (float)VL_BLOCK_WIDTH / idct->buffer_width,
                       (float)VL_BLOCK_HEIGHT / idct->buffer_height);

    ureg_MAD(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_XY), vpos, scale, scale);
    ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_ZW), ureg_imm1f(shader, 1.0f));

    ureg_MUL(shader, ureg_writemask(t_tex, TGSI_WRITEMASK_XY), vpos, scale);
    calc_addr(shader, o_addr, ureg_src(t_tex), ureg_src(t_tex), false, false, idct->buffer_width / 4);

    ureg_release_temporary(shader, t_tex);

    ureg_END(shader);

    return ureg_create_shader_and_destroy(shader, idct->pipe);
}
Ejemplo n.º 11
0
/*
 *   Decrement the write offset 
 */
void CTcDataStream::dec_ofs(int amount)
{
    /* adjust the offset */
    ofs_ -= amount;

    /* 
     *   calculate the new page we're on, since this may take us to a
     *   different page 
     */
    page_cur_ = ofs_ / TCCS_PAGE_SIZE;

    /* calculate the remaining size in this page */
    rem_ = TCCS_PAGE_SIZE - (ofs_ % TCCS_PAGE_SIZE);

    /* calculate the current write pointer */
    wp_ = calc_addr(ofs_);
}
Ejemplo n.º 12
0
static int finalexpansion_mon_dump(void)
{
    BYTE mode;
    int blk, active, ro;

    mode = register_a & REGA_MODE_MASK;

    mon_out("Register A: $%02x, B: $%02x, lock bit %i\n", register_a, register_b, lock_bit);
    mon_out("Mode: %s\n", finalexpansion_mode_name[mode >> 5]);

    /* BLK 0 */
    mon_out("BLK 0: ");
    active = 0;
    ro = 0;

    if (!(register_b & REGB_BLK0_OFF)) {
        switch (mode) {
            case MODE_SUPER_ROM:
            case MODE_SUPER_RAM:
                active = 1;
                break;
            case MODE_ROM_RAM:
            case MODE_RAM1:
            case MODE_RAM2:
                active = 1;
                ro = register_a & REGA_BLK0_RO;
                break;
            default:
                break;
        }
    }

    if (active) {
        mon_out("RAM%s (offset $%06x)\n", ro ? " (read only)" : "", calc_addr(0, 0, BLK0_BASE));
    } else {
        mon_out("off\n");
    }

    /* BLK 1, 2, 3, 5 */
    for (blk = 1; blk <= 5; blk++) {
        finalexpansion_mon_dump_blk(blk);
    }

    return 0;
}
Ejemplo n.º 13
0
/*
 *   Write bytes to the stream at an earlier offset 
 */
void CTcDataStream::write_at(ulong ofs, const char *buf, size_t len)
{
    /* if we're writing to the current offset, use the normal writer */
    if (ofs == ofs_)
        write(buf, len);
    
    /* 
     *   log an internal error, and skip writing anything, if the desired
     *   range of offsets has not been previously written 
     */
    if (ofs + len > ofs_)
        G_tok->throw_internal_error(TCERR_WRITEAT_PAST_END);

    /* write the data to each page it spans */
    while (len != 0)
    {
        size_t cur;

        /* 
         *   determine how much is left on the page containing the current
         *   starting offset 
         */
        cur = TCCS_PAGE_SIZE - (ofs % TCCS_PAGE_SIZE);

        /* 
         *   figure out how much we can copy - copy the whole remaining
         *   size, but no more than the amount remaining on this page 
         */
        if (cur > len)
            cur = len;

        /* copy the data */
        memcpy(calc_addr(ofs), buf, cur);

        /* advance past this chunk */
        len -= cur;
        ofs += cur;
        buf += cur;
    }
}
Ejemplo n.º 14
0
static BYTE internal_read(WORD addr, int blk, WORD base, int sel)
{
    BYTE mode;
    int bank;
    unsigned int faddr;
    BYTE value;

    mode = register_a & REGA_MODE_MASK;

    /* Determine which bank to access */
    switch (mode) {
        case MODE_FLASH:
        case MODE_SUPER_ROM:
        case MODE_SUPER_RAM:
            bank = register_a & REGA_BANK_MASK;
            break;
        case MODE_ROM_RAM:
        case MODE_RAM1:
            bank = 1;
            break;
        case MODE_RAM2:
            if (sel) {
                bank = 2;
            } else {
                bank = 1;
            }
            break;
        default:
            bank = 0;
            break;
    }

    /* Calculate Address */
    faddr = calc_addr(addr, bank, base);

    /* Perform access */
    switch (mode) {
        case MODE_START:
            if (blk == 5) {
                value = flash040core_read(&flash_state, faddr);
            } else {
                value = vic20_cpu_last_data;
            }
            break;
        case MODE_FLASH:
        case MODE_SUPER_ROM:
            value = flash040core_read(&flash_state, faddr);
            break;
        case MODE_ROM_RAM:
            if (sel) {
                value = flash040core_read(&flash_state, faddr);
            } else {
                value = cart_ram[faddr];
            }
            break;
        case MODE_RAM1:
        case MODE_RAM2:
        case MODE_SUPER_RAM:
            value = cart_ram[faddr];
            break;
        default:
            value = vic20_cpu_last_data;
            break;
    }
    return value;
}
Ejemplo n.º 15
0
/*
 *   Write the stream, its anchors, and its fixups to an object file. 
 */
void CTcDataStream::write_to_object_file(CVmFile *fp)
{
    ulong ofs;
    CTcStreamAnchor *anchor;
    long cnt;
    
    /* 
     *   First, write the data stream bytes.  Write the length prefix
     *   followed by the data.  Just blast the whole thing out in one huge
     *   byte stream, one page at a time.  
     */
    fp->write_int4(ofs_);

    /* write the data one page at a time */
    for (ofs = 0 ; ofs < ofs_ ; )
    {
        size_t cur;

        /* 
         *   write out one whole page, or the balance of the current page
         *   if we have less than a whole page remaining 
         */
        cur = TCCS_PAGE_SIZE;
        if (ofs + cur > ofs_)
            cur = (size_t)(ofs_ - ofs);

        /* write out this chunk */
        fp->write_bytes(calc_addr(ofs), cur);

        /* move to the next page's offset */
        ofs += cur;
    }

    /* count the anchors */
    for (cnt = 0, anchor = first_anchor_ ; anchor != 0 ;
         anchor = anchor->nxt_, ++cnt) ;

    /* write the count */
    fp->write_int4(cnt);

    /*
     *   Write all of the anchors, and all of their fixups.  (We have the
     *   code to write the anchor and fixup information in-line here for
     *   efficiency - there will normally be a large number of these tiny
     *   objects, so anything we can do to improve the speed of this loop
     *   will help quite a lot in the overall write performance.)
     */
    for (anchor = first_anchor_ ; anchor != 0 ; anchor = anchor->nxt_)
    {
        char buf[6];

        /* write the stream offset */
        oswp4(buf, anchor->get_ofs());

        /* 
         *   If the anchor has an external fixup list, write the symbol's
         *   name to the file; otherwise write a zero length to indicate
         *   that we have an internal fixup list.  
         */
        if (anchor->get_fixup_owner_sym() == 0)
        {
            /* no external list - indicate with a zero symbol length */
            oswp2(buf+4, 0);
            fp->write_bytes(buf, 6);
        }
        else
        {
            /* external list - write the symbol length and name */
            oswp2(buf+4, anchor->get_fixup_owner_sym()->get_sym_len());
            fp->write_bytes(buf, 6);
            fp->write_bytes(anchor->get_fixup_owner_sym()->get_sym(),
                            anchor->get_fixup_owner_sym()->get_sym_len());
        }

        /* write the fixup list */
        CTcAbsFixup::
            write_fixup_list_to_object_file(fp, *anchor->fixup_list_head_);
    }
}
Ejemplo n.º 16
0
static void internal_store(WORD addr, BYTE value, int blk, WORD base, int sel)
{
    BYTE mode;
    int bank;
    unsigned int faddr;

    mode = register_a & REGA_MODE_MASK;

    /* Determine which bank to access */
    switch (mode) {
        case MODE_FLASH:
        case MODE_SUPER_RAM:
            bank = register_a & REGA_BANK_MASK;
            break;
        case MODE_SUPER_ROM:
#ifdef FE3_2_SUPER_ROM_BUG
            bank = 1 | (register_a & REGA_BANK_MASK);
            break;
#endif
        case MODE_START:
            bank = 1;
            break;
        case MODE_ROM_RAM:
        case MODE_RAM1:
            if (sel) {
                bank = 2;
            } else {
                bank = 1;
            }
            break;
        case MODE_RAM2:
            bank = 1;
            break;
        default:
            bank = 0;
            break;
    }

    /* Calculate Address */
    faddr = calc_addr(addr, bank, base);

    /* Perform access */
    switch (mode) {
        case MODE_FLASH:
            flash040core_store(&flash_state, faddr, value);
            break;
        case MODE_ROM_RAM:
            if (sel) {
                cart_ram[faddr] = value;
            }
            break;
        case MODE_START:
        case MODE_RAM1:
        case MODE_RAM2:
        case MODE_SUPER_ROM:
        case MODE_SUPER_RAM:
            cart_ram[faddr] = value;
            break;
        default:
            break;
    }
}
Ejemplo n.º 17
0
static void finalexpansion_mon_dump_blk(int blk)
{
    int mode;
    BYTE reg_mask;
    int sel;
    int bank_r, bank_w;
    WORD base;
    enum { ACC_OFF, ACC_RAM, ACC_FLASH } acc_mode_r, acc_mode_w;

    switch (blk) {
        case 1:
            reg_mask = REGA_BLK1_SEL;
            base = BLK1_BASE;
            break;
        case 2:
            reg_mask = REGA_BLK2_SEL;
            base = BLK2_BASE;
            break;
        case 3:
            reg_mask = REGA_BLK3_SEL;
            base = BLK3_BASE;
            break;
        case 5:
            reg_mask = REGA_BLK5_SEL;
            base = BLK5_BASE;
            break;
        default:
            /* ignore block 4 */
            return;
    }

    mon_out("BLK %i: ", blk);

    if (register_b & reg_mask) {
        mon_out("off\n");
        return;
    }

    mode = register_a & REGA_MODE_MASK;
    sel = register_a & reg_mask;

    bank_r = register_a & REGA_BANK_MASK;
    bank_w = bank_r;

    switch (mode) {
        default:
        case MODE_START:
            bank_r = 0;
            bank_w = 1;
            acc_mode_r = (blk == 5) ? ACC_FLASH : ACC_OFF;
            acc_mode_w = ACC_RAM;
            break;
        case MODE_FLASH:
            acc_mode_r = ACC_FLASH;
            acc_mode_w = ACC_FLASH;
            break;
        case MODE_SUPER_ROM:
#ifdef FE3_2_SUPER_ROM_BUG
            bank_w = 1 | (register_a & REGA_BANK_MASK);
#endif
            acc_mode_r = ACC_FLASH;
            acc_mode_w = ACC_RAM;
            break;
        case MODE_SUPER_RAM:
            acc_mode_r = ACC_RAM;
            acc_mode_w = ACC_RAM;
            break;
        case MODE_ROM_RAM:
            bank_r = 1;
            bank_w = sel ? 2 : 1;
            acc_mode_r = sel ? ACC_FLASH : ACC_RAM;
            acc_mode_w = sel ? ACC_RAM : ACC_OFF;
            break;
        case MODE_RAM1:
            bank_r = 1;
            bank_w = sel ? 2 : 1;
            acc_mode_r = ACC_RAM;
            acc_mode_w = ACC_RAM;
            break;
        case MODE_RAM2:
            bank_r = sel ? 2 : 1;
            bank_w = 1;
            acc_mode_r = ACC_RAM;
            acc_mode_w = ACC_RAM;
            break;
    }

    mon_out("\n  read %s ", finalexpansion_acc_mode[acc_mode_r]);

    if (acc_mode_r != ACC_OFF) {
        mon_out("bank $%02x (offset $%06x)", bank_r, calc_addr(0, bank_r, base));
    }

    mon_out("\n write %s ", finalexpansion_acc_mode[acc_mode_w]);

    if (acc_mode_w != ACC_OFF) {
        mon_out("bank $%02x (offset $%06x)", bank_w, calc_addr(0, bank_w, base));
    }

    mon_out("\n");
}
Ejemplo n.º 18
0
//----------------------------------------------------------------------
static void handle_operand(op_t &x, bool read_access)
{
  ea_t ea;
  dref_t dreftype;
  switch ( x.type )
  {
    case o_void:
    case o_reg:
      break;

    case o_imm:
      QASSERT(557, read_access);
      dreftype = dr_O;
MAKE_IMMD:
      doImmdValue();
      if ( isOff(uFlag, x.n) )
        ua_add_off_drefs(x, dreftype);
      break;

    case o_displ:
      dreftype = read_access ? dr_R : dr_W;
      switch ( x.phrase )
      {
        case rD:        // "dp"
        case rDX:       // "dp, X"
        case rDY:       // "dp, Y"
        case riDX:      // "(dp, X)"
        case rDi:       // "(dp,n)"
        case rDiL:      // "long(dp,n)"
        case rDiY:      // "(dp,n), Y"
        case rDiLY:     // "long(dp,n), Y"
          {
            sel_t dp = get_segreg(cmd.ea, rD);
            if ( dp != BADSEL )
            {
              ea_t orig_ea = dp + x.addr;
              ea = xlat(orig_ea);
              goto MAKE_DREF;
            }
            else
            {
              goto MAKE_IMMD;
            }
          }

        case rAbsi:     // "(abs)"
        case rAbsX:     // "abs, X"
        case rAbsY:     // "abs, Y"
        case rAbsiL:    // "long(abs)"
          ea = toEA(dataSeg_op(x.n), x.addr);
          goto MAKE_DREF;

        case rAbsXi:    // "(abs,X)"
          ea = toEA(codeSeg(cmd.ea, x.n), x.addr); // jmp, jsr
          goto MAKE_DREF;

        case rAbsLX:    // "long abs, X"
          ea = x.addr;
          goto MAKE_DREF;

        default:
          goto MAKE_IMMD;
      }

    case o_mem:
    case o_mem_far:
      ea = calc_addr(x);
MAKE_DREF:
      ua_dodata2(x.offb, ea, x.dtyp);
      if ( !read_access )
        doVar(ea);
      ua_add_dref(x.offb, ea, read_access ? dr_R : dr_W);
      break;

    case o_near:
    case o_far:
      {
        ea_t orig_ea;
        ea = calc_addr(x, &orig_ea);
        if ( cmd.itype == M65816_per )
        {
          ua_add_dref(x.offb, ea, dr_O);
        }
        else
        {
          bool iscall = InstrIsSet(cmd.itype, CF_CALL);
          cref_t creftype = x.type == o_near
                          ? iscall ? fl_CN : fl_JN
                          : iscall ? fl_CF : fl_JF;
          ua_add_cref(x.offb, ea, creftype);
          if ( flow && iscall )
            flow = func_does_return(ea);
        }
      }
      break;

    default:
      INTERR(558);
  }
}