示例#1
0
文件: out.cpp 项目: nealey/vera
//----------------------------------------------------------------------
bool outop( op_t &x )
{
    uval_t v, v1;
//  const char *ptr;

    switch( x.type )
    {
    case o_imm:
        out_symbol( '#' );
        OutValue( x, OOF_SIGNED | OOFW_IMM );
        break;

    case o_indexed:
        OutValue( x, OOF_ADDR|OOF_SIGNED|(is_ext_insn() ? OOFW_32 : OOFW_16) ); //.addr
        v = x.value;
        out_symbol( '[' );
        if ( v != 0 ) goto OUTPHRASE;
        out_symbol( ']' );
        break;

    case o_indirect:
    case o_indirect_inc:
        out_symbol( '[' );

    case o_mem:
    case o_near:
        v = x.addr;
OUTPHRASE:
        v1 = toEA( getSR(cmd.ea, (x.type == o_near) ? rVcs : rVds), v);
        if( !out_name_expr( x, v1, v ) )
        {
            OutValue( x, (x.type == o_indexed ? 0 : OOF_ADDR) | OOF_NUMBER|OOFS_NOSIGN|
                      ((x.type == o_near) ? (is_ext_insn() ? OOFW_32 : OOFW_16) : OOFW_8) );
            QueueMark( Q_noName, cmd.ea );
        }

        if( x.type == o_indirect || x.type == o_indirect_inc ||
                x.type == o_indexed )
        {
            out_symbol( ']' );
            if( x.type == o_indirect_inc )    out_symbol( '+' );
        }
        break;

    case o_void:
        return 0;

    case o_bit:
        out_symbol( char('0' + x.reg) );
        break;

    default:
        warning( "out: %a: bad optype %d", cmd.ea, x.type );
    }

    return 1;
}
示例#2
0
//--------------------------------------------------------------------------
// if bit0 is set, ensure that thumb mode
// if bit0 is clear, ensure that arm mode
static void handle_arm_thumb_modes(ea_t ea)
{
  bool should_be_thumb = (ea & 1) != 0;
  bool is_thumb = getSR(ea, ARM_T);
  if ( should_be_thumb != is_thumb )
  {
    int code = processor_t::loader + (should_be_thumb ? 0 : 1);
    ph.notify(processor_t::idp_notify(code), ea & ~1);
  }
}
示例#3
0
文件: out.cpp 项目: nealey/vera
//--------------------------------------------------------------------------
// function to produce assume directives
void idaapi assumes(ea_t ea)
{
  segreg_t *Darea  = getSRarea(ea);
  segment_t *Sarea = getseg(ea);
  if ( Sarea == NULL || Darea == NULL || !inf.s_assume ) return;

  for ( int i=ph.regFirstSreg; i <= ph.regLastSreg; i++ )
  {
    if ( i == ph.regCodeSreg ) continue;
    sel_t now  = getSR(ea, i);
    bool show = (ea == Sarea->startEA);
    if ( show || Darea->startEA == ea )
    {
      segreg_t *prev = getSRarea(ea-1);
      if ( show || (prev != NULL && getSR(prev->startEA, i) != now) )
        print_segment_register(i, now);
    }
  }
}
示例#4
0
文件: emu.cpp 项目: nealey/vera
//------------------------------------------------------------------------
ea_t calc_data_mem(op_t &op)
{
    ea_t addr = op.addr;
    sel_t dph = 0;
    if (op.tms_regH == DPH)
    {
        dph = getSR(toEA(cmd.cs, cmd.ip), DPH);
        if ( dph == BADSEL ) return BADSEL;
        addr &= 0xFFFF;
    }
    sel_t dp = 0;
    if (op.tms_regP == DP)
    {
        dp = getSR(toEA(cmd.cs, cmd.ip), DP);
        if ( dp == BADSEL ) return BADSEL;
        addr &= 0xFFFF;
    }
    return (((dph & 0x7F) << 16) | (dp + addr)) << 1;
}
示例#5
0
文件: emu.cpp 项目: nealey/vera
//------------------------------------------------------------------------
ea_t calc_code_mem(ea_t ea, bool is_near)
{
  if (is_near)
  {
    sel_t xpc = getSR(cmd.ea, XPC);
    if ( xpc == BADSEL ) xpc = 0;
    return ((xpc & 0x7F) << 16) | (ea & 0xFFFF);
  }
  return toEA(cmd.cs, ea);
}
示例#6
0
文件: emu.cpp 项目: nealey/vera
ea_t calc_io_mem(op_t &op)
{
    ea_t addr = op.addr;
    sel_t pdp = 0;
    if (op.tms_regP == PDP)
    {
        pdp = getSR(toEA(cmd.cs, cmd.ip), PDP);
        if ( pdp == BADSEL ) return BADSEL;
        addr &= 0x7F;
    }
    ea_t ea = ((pdp & 0x1FF) << 7) | addr;
    return toEA(cmd.cs, ea);
}
示例#7
0
文件: emu.cpp 项目: nealey/vera
ea_t calc_data_mem(ea_t ea, bool is_mem)
{
  if (is_mem)
  {
    sel_t dp = getSR(cmd.ea, DP);
    if ( dp == BADSEL ) return BADSEL;
    return ((dp & 0x1FF) << 7) | (ea & 0x7F) + dataseg;
  }
  else
  {
    return dataseg + ea;
  }
}
示例#8
0
//----------------------------------------------------------------------
ea_t calc_mem(op_t &x)
{
  if ( x.type == o_near )
    return toEA(cmd.cs, x.addr);

// Before this was simply toEA, now we do it like this:
// (if someone complains, both methods should be retained)
  ea_t ea = x.addr;
  switch ( calc_sizer(x) )
  {
    case 8:
      if ( cmd.auxpref & aux_page )
      {
        ea &= 0xFF;
        sel_t br = getSR(cmd.ea, BR);
        if ( br != BADSEL )
          ea |= br << 8;
        else
          ea = BADADDR;
      }
      break;
    case 16:
      ea &= 0xFFFF;
      if ( x.type == o_mem )
      {
        sel_t dp = getSR(cmd.ea, DP);
        if ( dp != BADSEL )
          ea |= dp << 16;
        else
          ea = BADADDR;
      }
      else
      {
        ea |= cmd.ea & ~0xFFFF;
      }
      break;
  }
  return ea;
}
示例#9
0
文件: emu.cpp 项目: nealey/vera
//----------------------------------------------------------------------
ea_t calc_mem(op_t &x)
{
  uint xaddr;

  if ( x.amode & amode_x )
  {
          if (x.amode & amode_short)
          {
                sel_t dpage = getSR(cmd.ea, PAGE);
                if ( dpage == BADSEL ) return BADSEL;
                xaddr = ((dpage & 0xFF) << 8) | uint(x.addr);
          }
          else
                xaddr = (uint)x.addr;

          return xmem == BADADDR ? BADADDR : xmem + xaddr;
  }

  return toEA(cmd.cs, x.addr);

}
示例#10
0
void idaapi run(int)
{
  static const char * nname;
  if ( ph.id == PLFM_MIPS )
    nname = "$ mips";
  else if ( ph.id == PLFM_ARM )
    nname = " $arm";
  else
    nname = "$ vmm functions";
  netnode n(nname);
  ea_t ea = get_screen_ea();    // get current address
  if ( !isCode(get_flags_novalue(ea)) ) return; // not an instruction
  ea_t callee = n.altval(ea)-1;         // get the callee address from the database
  // remove thumb bit for arm
  if ( ph.id == PLFM_ARM )
    callee &= ~1;
  char buf[MAXSTR];
  qsnprintf(buf, sizeof(buf), form, help);
  if ( AskUsingForm_c(buf, &callee) )
  {
    if ( callee == BADADDR )
    {
      n.altdel(ea);
    }
    else
    {
      if ( ph.id == PLFM_ARM && (callee & 1) == 0 )
      {
        // if we're calling a thumb function, set bit 0
        sel_t tbit = getSR(callee, T);
        if ( tbit != 0 && tbit != BADSEL )
          callee |= 1;
      }
      n.altset(ea, callee+1);     // save the new address
    }
    noUsed(ea);                 // reanalyze the current instruction
  }
}
示例#11
0
文件: emu.cpp 项目: nealey/vera
//----------------------------------------------------------------------
// change value of virtual register "BANK" and switch to another bank
static void split(int reg, sel_t v)
{
    if ( reg == -1 )
    {
        flow = 0;
        if ( v != BADSEL )
        {
            sel_t pclath = getSR(cmd.ea, PCLATH) & 0x1F;
            ea_t ea = calc_code_mem(uchar(v) | (pclath<<8));
            ua_add_cref(0, ea, fl_JN);
        }
    }
    else
    {
        if ( v == BADSEL ) v = 0;     // assume bank0 if bank is unknown
        if ( reg == BANK )
        {
            if ( ptype != PIC16 ) v &= 3;
            else v &= 0xF;
        }
        splitSRarea1(get_item_end(cmd.ea), reg, v, SR_auto);
    }
}
示例#12
0
文件: out.cpp 项目: nealey/vera
// Get description for a given general register.
// Description may change according to the current number of the registers page.
static const char * get_general_register_description(const ushort reg) {
    if ( reg < rR240 || reg > rR255 )
        return NULL;

    switch ( getSR(cmd.ea, rRP) ) {
        // page: N/A
        case BADSEL:
            switch ( reg ) {
                case rR230:     return "Central Interrupt Control Register";
                case rR231:     return "Flag Register";
                case rR232:     return "Pointer 0 Register";
                case rR233:     return "Pointer 1 Register";
                case rR234:     return "Page Pointer Register";
                case rR235:     return "Mode Register";
                case rR236:     return "User Stack Pointer High Register";
                case rR237:     return "User Stack Pointer Low Register";
                case rR238:     return "System Stack Pointer High Register";
                case rR239:     return "System Stack Pointer Low Register";
            }
            break;

        // page: 0
        case 0:
            switch ( reg ) {
                case rR241:     return "Minor Register";
                case rR242:     return "External Interrupt Trigger Register";
                case rR243:     return "External Interrupt Pending Register";
                case rR244:     return "External Interrupt Mask-bit Register";
                case rR245:     return "External Interrupt Priority Level Register";
                case rR246:     return "External Interrupt Vector Register";
                case rR247:     return "Nested Interrupt Control";
                case rR248:     return "Watchdog Timer High Register";
                case rR249:     return "Watchdog Timer Low Register";
                case rR250:     return "Watchdog Timer Prescaler Register";
                case rR251:     return "Watchdog Timer Control Register";
                case rR252:     return "Wait Control Register";
                case rR253:     return "SPI Data Register";
                case rR254:     return "SPI Control Register";
            }
            break;

        // page: 2
        case 2:
            switch ( reg ) {
                case rR240:     return "Port 0 Configuration Register 0";
                case rR241:     return "Port 0 Configuration Register 1";
                case rR242:     return "Port 0 Configuration Register 2";
                case rR244:     return "Port 1 Configuration Register 0";
                case rR245:     return "Port 1 Configuration Register 1";
                case rR246:     return "Port 1 Configuration Register 2";
                case rR248:     return "Port 2 Configuration Register 0";
                case rR249:     return "Port 2 Configuration Register 1";
                case rR250:     return "Port 2 Configuration Register 2";
            }
            break;

        // page: 3
        case 3:
            switch ( reg ) {
                case rR240:     return "Port 4 Configuration Register 0";
                case rR241:     return "Port 4 Configuration Register 1";
                case rR242:     return "Port 4 Configuration Register 2";
                case rR244:     return "Port 5 Configuration Register 0";
                case rR245:     return "Port 5 Configuration Register 1";
                case rR246:     return "Port 5 Configuration Register 2";
                case rR248:     return "Port 6 Configuration Register 0";
                case rR249:     return "Port 6 Configuration Register 1";
                case rR250:     return "Port 6 Configuration Register 2";
                case rR251:     return "Port 6 Data Register";
                case rR252:     return "Port 7 Configuration Register 0";
                case rR253:     return "Port 7 Configuration Register 1";
                case rR254:     return "Port 7 Configuration Register 2";
                case rR255:     return "Port 7 Data Register";
            }
            break;

        // page: 8, 10 or 12
        case 8:
        case 10:
        case 12:
            switch ( reg ) {
                case rR240:     return "Capture Load Register 0 High";
                case rR241:     return "Capture Load Register 0 Low";
                case rR242:     return "Capture Load Register 1 High";
                case rR243:     return "Capture Load Register 1 Low";
                case rR244:     return "Compare 0 Register High";
                case rR245:     return "Compare 0 Register Low";
                case rR246:     return "Compare 1 Register High";
                case rR247:     return "Compare 1 Register Low";
                case rR248:     return "Timer Control Register";
                case rR249:     return "Timer Mode Register";
                case rR250:     return "External Input Control Register";
                case rR251:     return "Prescaler Register";
                case rR252:     return "Output A Control Register";
                case rR253:     return "Output B Control Register";
                case rR254:     return "Flags Register";
                case rR255:     return "Interrupt/DMA Mask Register";
            }
            break;

        // page: 9
        case 9:
            switch ( reg ) {
                case rR240:
                case rR244:     return "DMA Counter Pointer Register";
                case rR241:
                case rR245:     return "DMA Address Pointer Register";
                case rR242:
                case rR246:     return "Interrupt Vector Register";
                case rR243:
                case rR247:     return "Interrupt/DMA Control Register";
                case rR248:     return "I/O Connection Register";
            }
            break;

        // page: 11
        case 11:
            switch ( reg ) {
                case rR240:     return "Counter High Byte Register";
                case rR241:     return "Counter Low Byte Register";
                case rR242:     return "Standard Timer Prescaler Register";
                case rR243:     return "Standard Timer Control Register";
            }
            break;

        // page: 13
        case 13:
            switch ( reg ) {
                case rR244:     return "DMA Counter Pointer Register";
                case rR245:     return "DMA Address Pointer Register";
                case rR246:     return "Interrupt Vector Register";
                case rR247:     return "Interrupt/DMA Control Register";
            }
            break;

        // page: 21
        case 21:
            switch ( reg ) {
                case rR240:     return "Data Page Register 0";
                case rR241:     return "Data Page Register 1";
                case rR242:     return "Data Page Register 2";
                case rR243:     return "Data Page Register 3";
                case rR244:     return "Code Segment Register";
                case rR248:     return "Interrupt Segment Register";
                case rR249:     return "DMA Segment Register";
                case rR245:     return "External Memory Register 1";
                case rR246:     return "External Memory Register 2";
            }

        // page: 24 or 25
        case 24:
        case 25:
            switch ( reg ) {
                case rR240:     return "Receiver DMA Transaction Counter Pointer";
                case rR241:     return "Receiver DMA Source Address Pointer";
                case rR242:     return "Transmitter DMA Transaction Counter Pointer";
                case rR243:     return "Transmitter DMA Source Address Pointer";
                case rR244:     return "Interrupt Vector Register";
                case rR245:     return "Address/Data Compare Register";
                case rR246:     return "Interrupt Mask Register";
                case rR247:     return "Interrupt Status Register";
                case rR248:     return "Receive/Transmitter Buffer Register";
                case rR249:     return "Interrupt/DMA Priority Register";
                case rR250:     return "Character Configuration Register";
                case rR251:     return "Clock Configuration Register";
                case rR252:     return "Baud Rate Generator High Register";
                case rR253:     return "Baud Rate Generator Low Register";
                case rR254:     return "Synchronous Input Control";
                case rR255:     return "Synchronous Output Control";
            }
            break;

        // page: 43
        case 43:
            switch ( reg ) {
                case rR248:     return "Port 8 Configuration Register 0";
                case rR249:     return "Port 8 Configuration Register 1";
                case rR250:     return "Port 8 Configuration Register 2";
                case rR251:     return "Port 8 Data Register";
                case rR252:     return "Port 9 Configuration Register 0";
                case rR253:     return "Port 9 Configuration Register 1";
                case rR254:     return "Port 9 Configuration Register 2";
                case rR255:     return "Port 9 Data Register";
            }
            break;

        // page: 55
        case 55:
            switch ( reg ) {
                case rR240:     return "Clock Control Register";
                case rR242:     return "Clock Flag Register";
                case rR246:     return "PLL Configuration Register";
            }
            break;

        // page: 63
        case 63:
            switch ( reg ) {
                case rR240:     return "Channel 0 Data Register";
                case rR241:     return "Channel 1 Data Register";
                case rR242:     return "Channel 2 Data Register";
                case rR243:     return "Channel 3 Data Register";
                case rR244:     return "Channel 4 Data Register";
                case rR245:     return "Channel 5 Data Register";
                case rR246:     return "Channel 6 Data Register";
                case rR247:     return "Channel 7 Data Register";
                case rR248:     return "Channel 6 Lower Threshold Register";
                case rR249:     return "Channel 6 Lower Threshold Register";
                case rR250:     return "Channel 7 Upper Threshold Register";
                case rR251:     return "Channel 7 Upper Threshold Register";
                case rR252:     return "Compare Result Register";
                case rR253:     return "Control Logic Register";
                case rR254:     return "Interrupt Control Register";
                case rR255:     return "Interrupt Vector Register";
            }
            break;
    }
    return NULL;
}
示例#13
0
文件: emu.cpp 项目: nealey/vera
// Emulate an instruction.
int emu(void) {
    uint32 feature = cmd.get_canon_feature();
    flow = ((feature & CF_STOP) == 0);

    if ( cmd.Op1.type != o_void) handle_operand(cmd.Op1, (feature & CF_CHG1) != 0 );
    if ( cmd.Op2.type != o_void) handle_operand(cmd.Op2, (feature & CF_CHG2) != 0 );
    if ( cmd.Op3.type != o_void) handle_operand(cmd.Op3, (feature & CF_CHG3) != 0 );

    if ( flow )
        ua_add_cref(0, cmd.ea + cmd.size, fl_F);

    //  Following code will update the current value of the two virtual
    //  segment registers: RW (register window) and RP (register page).

    bool rw_has_changed = false;
    bool rp_has_changed = false;

    switch ( cmd.itype ) {
        case st9_srp:
            {
                sel_t val = cmd.Op1.value;
                if ( val % 2 ) val--;     // even reduced
                splitSRarea1(cmd.ea, rRW, val | (val << 8), SR_auto);
            }
            rw_has_changed = true;
            break;

        case st9_srp0:
            {
                sel_t RW = getSR(cmd.ea, rRW);
                splitSRarea1(cmd.ea, rRW, cmd.Op1.value | (RW & 0xFF00), SR_auto);
            }
            rw_has_changed = true;
            break;

        case st9_srp1:
            {
                sel_t RW = getSR(cmd.ea, rRW);
                splitSRarea1(cmd.ea, rRW, (cmd.Op1.value << 8) | (RW & 0x00FF), SR_auto);
            }
            rw_has_changed = true;
            break;

        case st9_spp:
            splitSRarea1(cmd.ea, rRP, cmd.Op1.value, SR_auto);
            rp_has_changed = true;
            break;
    }

    // If RW / RP registers have changed, print a comment which explains the new mapping of
    // the general registers.

    if ( rw_has_changed && !has_cmt(uFlag) ) {
        char buf[MAXSTR];
        sel_t RW = getSR(cmd.ea, rRW);
        int low = RW & 0x00FF;
        int high = (RW & 0xFF00) >> 8;

        low *= 8;
        high *= 8;

        const char *fmt =
            "r0 -> R%d, r1 -> R%d, r2 -> R%d, r3 -> R%d, r4 -> R%d, r5 -> R%d, r6 -> R%d, r7 -> R%d,\n"
            "r8 -> R%d, r9 -> R%d, r10 -> R%d, r11 -> R%d, r12 -> R%d, r13 -> R%d, r14 -> R%d, r15 -> R%d";

        qsnprintf(buf, sizeof buf, fmt,
            0 + low,
            1 + low,
            2 + low,
            3 + low,
            4 + low,
            5 + low,
            6 + low,
            7 + low,
            8 + high,
            9 + high,
            10 + high,
            11 + high,
            12 + high,
            13 + high,
            14 + high,
            15 + high
        );

        set_cmt(cmd.ea, buf, false);
    }
示例#14
0
文件: z8.hpp 项目: nealey/vera
//------------------------------------------------------------------------
inline uint16 get_rp(ea_t ea)
{
  sel_t t = getSR(ea, rRp);
  return t != BADSEL ? t : 0;
}
示例#15
0
文件: emu.cpp 项目: nealey/vera
//------------------------------------------------------------------------
ea_t calc_data_mem(op_t &x)
{
    sel_t dpage = getSR(cmd.ea, dp);
    if ( dpage == BADSEL ) return BADSEL;
    return ((dpage & 0xFF) << 16) | (x.addr);
}
示例#16
0
文件: emu.cpp 项目: nealey/vera
//----------------------------------------------------------------------
int idaapi emu(void)
{
    uint32 Feature = cmd.get_canon_feature();
    int flag1 = is_forced_operand(cmd.ea, 0);
    int flag2 = is_forced_operand(cmd.ea, 1);
    int flag3 = is_forced_operand(cmd.ea, 2);

    flow = (Feature & CF_STOP) == 0;

    if ( Feature & CF_USE1 ) process_operand(cmd.Op1, flag1, 1);
    if ( Feature & CF_USE2 ) process_operand(cmd.Op2, flag2, 1);
    if ( Feature & CF_USE3 ) process_operand(cmd.Op3, flag3, 1);

    if ( Feature & CF_CHG1 ) process_operand(cmd.Op1, flag1, 0);
    if ( Feature & CF_CHG2 ) process_operand(cmd.Op2, flag2, 0);
    if ( Feature & CF_CHG3 ) process_operand(cmd.Op3, flag3, 0);

//
//      Check for:
//        - the register bank changes
//        - PCLATH changes
//        - PCL changes
//
    for ( int i=0; i < 3; i++ )
    {
        int reg = 0;
        switch ( i )
        {
        case 0:
            reg = BANK;
            if ( !is_bank() ) continue;
            break;
        case 1:
            reg = PCLATH;
            if ( !is_pclath() ) continue;
            break;
        case 2:
            reg = -1;
            if ( !is_pcl() ) continue;
            break;
        }
        sel_t v = (reg == -1) ? cmd.ip : getSR(cmd.ea, reg);
        if ( cmd.Op2.type == o_reg && cmd.Op2.reg == F )
        {
//      split(reg, v);
        }
        else
        {
            switch ( cmd.itype )
            {
            case PIC_bcf:
            case PIC_bcf3:
            case PIC_bsf:
            case PIC_bsf3:
                if ( ((ptype == PIC12) && (cmd.Op2.value == 5) )  // bank selector
                        || ((ptype == PIC14) && (
                                (reg == BANK && (cmd.Op2.value == 5 || cmd.Op2.value == 6))
                                || (reg == PCLATH && (cmd.Op2.value == 3 || cmd.Op2.value == 4))))
                        || ((ptype == PIC16) && (sval_t(cmd.Op2.value) >= 0 && cmd.Op2.value <= 3)))
                {
                    if ( v == BADSEL ) v = 0;
                    int shift = 0;
                    if ( ptype == PIC14 && reg == BANK ) shift = 5;
                    if ( cmd.itype == PIC_bcf ) v = v & ~(1 << (cmd.Op2.value-shift));
                    else v = v | (1 << (cmd.Op2.value-shift));
                    split(reg, v);
                }
                break;
            case PIC_clrf:
            case PIC_clrf2:
                split(reg, 0);
                break;
            case PIC_swapf:
            case PIC_swapf3:
                split(reg, ((v>>4) & 15) | ((v & 15) << 4));
                break;
            case PIC_movwf:
            case PIC_movwf2:
            case PIC_addlw:
            case PIC_andlw:
            case PIC_iorlw:
            case PIC_sublw:
            case PIC_xorlw:
            {
                insn_t saved = cmd;
                if ( decode_prev_insn(cmd.ea) != BADADDR
                        && ( cmd.itype == PIC_movlw ) )
                {
                    switch ( saved.itype )
                    {
                    case PIC_movwf:
                    case PIC_movwf2:
                        v = cmd.Op1.value;
                        break;
                    case PIC_addlw:
                        v += cmd.Op1.value;
                        break;
                    case PIC_andlw:
                        v &= cmd.Op1.value;
                        break;
                    case PIC_iorlw:
                        v |= cmd.Op1.value;
                        break;
                    case PIC_sublw:
                        v -= cmd.Op1.value;
                        break;
                    case PIC_xorlw:
                        v ^= cmd.Op1.value;
                        break;
                    }
                }
                else
                {
                    v = BADSEL;
                }
                cmd = saved;
            }
            split(reg, v);
            break;
            case PIC_movlw:
                split(reg, cmd.Op2.value);
                break;
            }
        }
    }

// Such as , IDA doesn't seem to convert the following:
// tris 6
// into
// tris PORTB ( or whatever )

    if ( cmd.itype == PIC_tris && !isDefArg0(uFlag) )
        set_offset(cmd.ea, 0, dataseg);

//   movlw value
// followed by a
//   movwf FSR
// should convert value into an offset , because FSR is used as a pointer to
// the INDF (indirect addressing file)

    if ( ptype == PIC12 || ptype == PIC14
            && cmd.itype == PIC_movwf
            && cmd.Op1.type == o_mem
            && (cmd.Op1.addr & 0x7F) == 0x4 )    // FSR
    {
        insn_t saved = cmd;
        if ( decode_prev_insn(cmd.ea) != BADADDR
                && cmd.itype == PIC_movlw )
        {
            set_offset(cmd.ea, 0, dataseg);
        }
        cmd = saved;
    }

// Also - it seems to make sense to me that a
//   movlw value
// followed by a
//   tris PORTn  (or movwf TRISn)
// should convert value into a binary , because the bits indicate whether a
// port is defined for input or output.

    if ( is_load_tris_reg() )
    {
        insn_t saved = cmd;
        if ( decode_prev_insn(cmd.ea) != BADADDR
                && cmd.itype == PIC_movlw )
        {
            op_bin(cmd.ea, 0);
        }
        cmd = saved;
    }

// Move litteral to BSR

    if ( cmd.itype == PIC_movlb1 ) split(BANK, cmd.Op1.value);

//
//      Determine if the next instruction should be executed
//
    if ( !flow ) flow = conditional_insn();
    if ( segtype(cmd.ea) == SEG_XTRN ) flow = 0;
    if ( flow ) ua_add_cref(0,cmd.ea+cmd.size,fl_F);

    return 1;
}