Example #1
0
        ///* disassembly */

        static int disop(DISTATE sp, DIS dp)
        {
            int tmp;
            int w;
            int err;

            StringBuilder opndbuf = new StringBuilder();
            StringBuilder commbuf = new StringBuilder();

            var opnd = opndbuf;

            int inst = dp.data[0];

            dp.flags = sp.flags;
            sp.flags = 0;

            switch (dp.opcode.type)
            {
                case itype.TYPE_A:
                    dp.i = (Reg)(0xF & inst);
                    dp.j = (Reg)(0xF & (inst >> 4));
                    break;
                case itype.TYPE_B:
                    dp.i = (Reg)(0xF & inst);
                    dp.x = (ulong)(0xFF & (inst >> 4));
                    dp.w = 8;
                    break;
                case itype.TYPE_C:
                    dp.i = (Reg)(0xF & inst);
                    dp.x = (ulong)(0xF & (inst >> 4));
                    dp.w = 4;
                    break;
                case itype.TYPE_D:
                    dp.x = (ulong)(0xFF & inst);
                    dp.w = 8;
                    break;
                case itype.TYPE_E:
                    dp.i = (Reg)(0xF & inst);
                    break;
                case itype.TYPE_F:
                    dp.x = (ulong)(0x7FF & inst);
                    dp.w = 11;
                    break;
                case itype.TYPE_Z:
                    dp.j = (Reg)(0xF & (inst >> 4));
                    break;
                case itype.TYPE_W:
                    dp.x = (ulong)(inst);
                    dp.w = 16;
                    break;
            }

            foreach (char s in dp.opcode.format)
            {
                switch (s)
                {
                    case '#':
                        opnd.Append(fmt.imm);
                        break;
                    case '&':
                        opnd.Append(fmt.and);
                        break;
                    case '(':
                        opnd.Append(fmt.par);
                        break;
                    case ')':
                        opnd.Append(fmt.ens);
                        break;
                    case '+':
                        opnd.Append(fmt.inc);
                        break;
                    case ',':
                        opnd.Append(fmt.nxt);
                        break;
                    case '-':
                        opnd.Append(fmt.dec);
                        break;
                    case ';':
                        opnd = commbuf;
                        break;
                    case '@':
                        opnd.Append(fmt.mem);
                        break;
                    case '2':
                        dp.x <<= 1;
                        dp.w += 1;
                        break;
                    case '4':
                        dp.x <<= 2;
                        dp.w += 2;
                        break;
                    case 'A':
                        opnd.Append(Reg.AC);
                        break;
                    case 'C':
                        opnd.Append(Reg.CCR);
                        break;
                    case 'F':
                        opnd.Append(Reg.FP);
                        break;
                    case 'J':
                        if (sp.IsValid(dp.j))
                        {
                            dp.x = sp.reg[(int)dp.j];
                            dp.w = 32;
                        }
                        else
                        {
                            dp.x = 0;
                            dp.w = 0;
                        }
                        break;
                    case 'I':
                        if (sp.IsValid(dp.i))
                        {
                            dp.x = sp.reg[(int)dp.i];
                            dp.w = 32;
                        }
                        else
                        {
                            dp.x = 0;
                            dp.w = 0;
                        }
                        break;
                    case 'M':
                        opnd.Append(Reg.ILM);
                        break;
                    case 'P':
                        opnd.Append(Reg.PS);
                        break;
                    case 'S':
                        opnd.Append(Reg.SP);
                        break;
                    case 'X':
                        /* constant extension word */
                        if ((err = getword(dp)) != 0)
                            return err;
                        dp.x = ((ulong)(dp.x << 16)) + ((ulong)dp.data[dp.n - 1]);
                        dp.w += 16;
                        break;
                    case 'Y':
                        /* coprocessor extension word */
                        if ((err = getword(dp)) != 0)
                            return err;
                        tmp = dp.data[dp.n - 1];
                        dp.x = (ulong)dp.i;
                        dp.w = 4;
                        dp.c = 0xFF & (tmp >> 8);
                        dp.j = (Reg)(0x0F & (tmp >> 4));
                        dp.i = (Reg)(0x0F & (tmp));
                        break;
                    case 'a':
                        w = dp.w;
                        while (w >= 8)
                        {
                            w -= 8;

                            opnd.Append(Asc((int)(dp.x >> w)));
                        }
                        break;
                    case 'b':
                        /* shift2 */
                        dp.x += 16;
                        dp.w += 1;
                        break;
                    case 'c':
                        /* coprocessor operation */
                        opnd.AppendFormat(fmt.u[8], dp.c);
                        break;
                    case 'd':
                        /* unsigned decimal */
                        opnd.AppendFormat(fmt.ud, dp.x);
                        break;
                    case 'f':
                        w = dp.w >> 1;
                        
                        tmp = (int)(((1ul << w) - 1) & (dp.x >> w));
                        int tmq = (int)(((1ul << w) - 1) & dp.x);
                        if (tmq != 0)
                            opnd.AppendFormat("{0:g}", ((double)tmp) / ((double)tmq));
                        else
                            opnd.Append("NaN");

                            break;
                    case 'g':
                        dp.i += SPECIALS;
                        goto case 'i';
                    case 'h':
                        dp.j += SPECIALS;
                        goto case 'j';
                    case 'i':
                        opnd.Append((Reg)dp.i);
                        break;
                    case 'j':
                        opnd.Append((Reg)dp.j);
                        break;
                    case 'k':
                        dp.i += COPROCESSOR;
                        goto case 'i';
                    case 'l':
                        dp.j += COPROCESSOR;
                        goto case 'j';
                    case 'n':
                        /* negative constant */
                        opnd.AppendFormat(fmt.u[dp.w + 1], dp.x);
                        //TODO opnd.AppendFormat(fmt.n[dp.w + 1], ((1ul << (dp.w + 1)) - 1) & NEG(dp.w, (1ul << dp.w) | dp.x));
                        break;
                    case 'p':
                        /* pair */
                        w = dp.w >> 1;
                        opnd.AppendFormat(fmt.u[w], ((1ul << w) - 1) & (dp.x >> w));
                        opnd.Append(fmt.nxt);
                        opnd.AppendFormat(fmt.u[w], ((1ul << w) - 1) & dp.x);
                        break;
                    case 'q':
                        /* rational */
                        w = dp.w >> 1;
                        opnd.AppendFormat(fmt.ud, ((1ul << w) - 1) & (dp.x >> w));
                        opnd.Append("/");
                        opnd.AppendFormat(fmt.ud, ((1ul << w) - 1) & dp.x);
                        break;
                    case 'r':
                        /* relative */
                        dp.x = (ulong)((long)dp.pc + 2 + SignExtend(dp.w, (int)dp.x));
                        dp.w = 32;
                        break;
                    case 's':
                        /* signed constant */
                        if (IsNeg(dp.w, dp.x))
                        {
                            if ((opt_outflag & OutOpt.OF_CSTYLE) != 0 && (opnd[-1] == '+'))
                                opnd.Remove(opnd.Length - 1, 1);
                            opnd.AppendFormat(fmt.n[dp.w], NEG(dp.w, (long)dp.x));
                        }
                        else
                        {
                            opnd.AppendFormat(fmt.u[dp.w - 1], dp.x);
                        }
                        break;
                    case 'u':
                        /* unsigned constant */
                        opnd.AppendFormat(fmt.u[dp.w], dp.x);
                        break;
                    case 'v':
                        /* vector */
                        opnd.AppendFormat(fmt.u[8], 0xFF - (0xFF & ((dp.pc - dp.memrange.start) / 4)));
                        break;
                    case 'x':
                        dp.x |= 0x100;
                        break;
                    case 'y':
                        dp.c += 8;
                        goto case 'z'; /*FALLTHROUGH*/
                    case 'z':
                        /* register list */
                        opnd.Append(fmt.par);
                        bool first = true;
                        for (int i = 0; i < 8; ++i)
                        {
                            if ((dp.x & (uint)(1 << i)) != 0)
                            {
                                if (first)
                                    first = false;
                                else
                                    opnd.Append(",");
                                if ((dp.x & 0x100) != 0)
                                    opnd.Append((Reg)(dp.c + 7 - i));
                                else
                                    opnd.Append((Reg)(dp.c + i));

                            }
                        }
                        opnd.Append(fmt.ens);
                        break;
                    default:
                        opnd.Append(s);
                        break;
                }
            }



            Reg r = Reg.NOREG;
            DF dflags = 0;
            foreach (var s in dp.opcode.action)
            {
                switch (s)
                {
                    case '!':
                        /* jump */
                        dflags |= DF.FLOW | DF.BREAK | DF.BRANCH;
                        break;
                    case '?':
                        /* branch */
                        dflags |= DF.FLOW | DF.BRANCH;
                        break;
                    case '(':
                        /* call */
                        dflags |= DF.FLOW | DF.CALL;
                        //Debug.WriteLine("CALL {0:X8} {1:x8}", dp.x, dp.pc);
                        break;
                    case ')':
                        /* return */
                        dflags |= DF.FLOW | DF.BREAK | DF.CALL;
                        break;
                    case '_':
                        /* delay */
                        dflags |= DF.DELAY;
                        break;
                    case 'A':
                        r = Reg.AC;
                        break;
                    case 'C':
                        r = Reg.CCR;
                        break;
                    case 'F':
                        r = Reg.FP;
                        break;
                    case 'P':
                        r = Reg.PS;
                        break;
                    case 'S':
                        r = Reg.SP;
                        break;
                    case 'i':
                        r = dp.i;
                        break;
                    case 'j':
                        r = dp.j;
                        break;
                    case 'w':
                        sp.SetInvalid(r);
                        break;
                    case 'v':
                        if (sp.OkReg(r))
                        {
                            sp.SetValid(r);
                            sp.reg[(int)r] = dp.x;
                        }
                        break;
                    case 'x':
                        r = Reg.NOREG;
                        break;
                    default:
                        Error("bad action '{0}'", s);
                        break;
                }
            }

            dp.flags |= dflags & DF.TO_KEEP;
            sp.flags |= dflags & DF.TO_COPY;
            if ((dflags & DF.DELAY) != 0)
                sp.flags |= dflags & DF.TO_DELAY;
            else
                dp.flags |= dflags & DF.TO_DELAY;

            /*XXX*/
            dp.opnds = opndbuf.ToString();
            if (commbuf.Length >0 && dp.memrange.data.mem == MemType.MEMTYPE_UNKNOWN)
            {
                //opnd = commbuf;
                for (int i = 0; i < dp.n; ++i)
                {
                    commbuf.Append(Asc(dp.data[i] >> 8));
                    commbuf.Append(Asc(dp.data[i]));
                }
            }
            dp.comment = commbuf.ToString();
            dp.writedis(outfp);


            return dp.n << 1;
        }