Example #1
0
        public AArch64Instruction Decode(AArch64Disassembler dasm, uint instr, string fmt)
        {
            AA64Opcode            opcode = this.opcode;
            List <MachineOperand> ops    = new List <MachineOperand>();
            MachineOperand        op     = null;
            int i = 0;
            int off;

            while (i < fmt.Length)
            {
                switch (fmt[i++])
                {
                default: throw new InvalidOperationException(string.Format("Bad format character {0}.", fmt[i - 1]));

                case ',':
                    continue;

                case 'B':   // Logical Bitmask
                    op = LogicalBitmask(dasm, instr, fmt[i++] == 'x');
                    break;

                case 'H':   // 16-bit Immediate constant
                    off = GetOffset(fmt, ref i);
                    op  = ArmImmediateOperand.Word32(GetImm(instr, off, 16));
                    break;

                case 'I':   // 12-bit Immediate constant
                    off = GetOffset(fmt, ref i);
                    op  = ArmImmediateOperand.Word32(GetImm(instr, off, 12));
                    break;

                case 'J':   // long relative branch
                    int offset = (((int)instr) << 6) >> 4;
                    op = new AddressOperand(dasm.rdr.Address + offset);
                    break;

                case 'W':   // (32-bit) W register operand
                    op = GetWReg(instr, GetOffset(fmt, ref i));
                    break;

                case 'X':   // (64-bit) X register operand
                    op = GetXReg(instr, GetOffset(fmt, ref i));
                    break;

                case 's':   // Shift operand by 12
                    off = GetOffset(fmt, ref i);
                    op  = ops[ops.Count - 1];
                    ops.RemoveAt(ops.Count - 1);
                    uint shiftCode = GetImm(instr, off, 2);
                    switch (shiftCode)
                    {
                    case 0: break;

                    case 1:
                        op = new ShiftOperand(op, Opcode.lsl, 12); break;

                    default: throw new FormatException("Reserved value for shift code.");
                    }
                    break;
                }
                ops.Add(op);
            }
            return(AArch64Instruction.Create(opcode, ops));
        }
Example #2
0
 public override AArch64Instruction Decode(AArch64Disassembler dasm, uint instr)
 {
     return(Decode(dasm, instr, format));
 }
Example #3
0
 public override AArch64Instruction Decode(AArch64Disassembler dasm, uint instr)
 {
     return(((instr & (1 << 23)) != 0 ? mov : logical).Decode(dasm, instr));
 }
Example #4
0
 public abstract AArch64Instruction Decode(AArch64Disassembler dasm, uint opcode);
Example #5
0
        // https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob;f=opcodes/aarch64-dis.c;h=c11f78f78ab8569db6ebf5295d8047aeeee338bd;hb=master
        // line 694

        /* Decode logical immediate for e.g. ORR <Wd|WSP>, <Wn>, #<imm>.  */

        ArmImmediateOperand LogicalBitmask(AArch64Disassembler dasm, uint value, bool is64)
        {
            ulong imm, mask;
            uint  N, R, S;
            uint  simd_size;

            // value = extract_fields (code, 0, 3, FLD_N, FLD_immr, FLD_imms);
            //sf = aarch64_get_qualifier_esize (inst->operands[0].qualifier) != 4;

            /* value is N:immr:imms.  */
            S = (value >> 10) & 0x3Fu;
            R = (value >> 16) & 0x3F;
            N = (value >> 22) & 0x1;

            if (!is64 && N == 1)
            {
                throw new InvalidOperationException();
            }

            /* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R
             * (in other words, right rotated by R), then replicated.  */
            if (N != 0)
            {
                simd_size = 64;
                mask      = 0xFFFFFFFFFFFFFFFFul;
            }
            else
            {
                switch (S)
                {
                case 0x00:
                case 0x01:
                case 0x02:
                case 0x03:
                case 0x04:
                case 0x05:
                case 0x06:
                case 0x07:
                case 0x08:
                case 0x09:
                case 0x0A:
                case 0x0B:
                case 0x0C:
                case 0x0D:
                case 0x0E:
                case 0x0F:
                case 0x10:
                case 0x11:
                case 0x12:
                case 0x13:
                case 0x14:
                case 0x15:
                case 0x16:
                case 0x17:
                case 0x18:
                case 0x19:
                case 0x1A:
                case 0x1B:
                case 0x1C:
                case 0x1D:
                case 0x1E:
                case 0x1F:
                    /* 0xxxxx */
                    simd_size = 32;
                    break;

                case 0x20:
                case 0x21:
                case 0x22:
                case 0x23:
                case 0x24:
                case 0x25:
                case 0x26:
                case 0x27:
                case 0x28:
                case 0x29:
                case 0x2A:
                case 0x2B:
                case 0x2C:
                case 0x2D:
                case 0x2E:
                case 0x2F:
                    /* 10xxxx */
                    simd_size = 16; S &= 0xf; break;

                case 0x30:
                case 0x31:
                case 0x32:
                case 0x33:
                case 0x34:
                case 0x35:
                case 0x36:
                case 0x37:
                    /* 110xxx */
                    simd_size = 8; S &= 0x7; break;

                case 0x38:
                case 0x39:
                case 0x3A:
                case 0x3B:
                    /* 1110xx */
                    simd_size = 4; S &= 0x3; break;

                case 0x3C:
                case 0x3D:
                case 0x3E:
                case 0x3F:
                    /* 11110x */
                    simd_size = 2; S &= 0x1; break;

                default: throw new InvalidOperationException();
                }
                mask = ((1ul << (int)simd_size) - 1);
                /* Top bits are IGNORED.  */
                R &= simd_size - 1;
            }
            /* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected.  */
            if (S == simd_size - 1)
            {
                throw new InvalidOperationException();
            }
            /* S+1 consecutive bits to 1.  */
            /* NOTE: S can't be 63 due to detection above.  */
            imm = (1ul << (int)(S + 1)) - 1;
            /* Rotate to the left by simd_size - R.  */
            if (R != 0)
            {
                imm = ((imm << (int)(simd_size - R)) & mask) | (imm >> (int)R);
            }
            /* Replicate the value according to SIMD size.  */
            switch (simd_size)
            {
            case 2: imm = (imm << 2) | imm; goto case 4;

            case 4: imm = (imm << 4) | imm; goto case 8;

            case 8: imm = (imm << 8) | imm; goto case 16;

            case 16: imm = (imm << 16) | imm; goto case 32;

            case 32: imm = (imm << 32) | imm; break;

            case 64: break;

            default: throw new InvalidOperationException();
            }

            return(is64
                ? dasm.Word64(imm)
                : dasm.Word32((int)imm));
        }