1329 lines
52 KiB
Plaintext
1329 lines
52 KiB
Plaintext
// Copyright (c) 2010 ARM Limited
|
|
// All rights reserved
|
|
//
|
|
// The license below extends only to copyright in the software and shall
|
|
// not be construed as granting a license to any other intellectual
|
|
// property including but not limited to intellectual property relating
|
|
// to a hardware implementation of the functionality of the software
|
|
// licensed hereunder. You may use the software subject to the license
|
|
// terms below provided that you ensure that this notice is replicated
|
|
// unmodified and in its entirety in all distributions of the software,
|
|
// modified or unmodified, in source code or in binary form.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions are
|
|
// met: redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer;
|
|
// redistributions in binary form must reproduce the above copyright
|
|
// notice, this list of conditions and the following disclaimer in the
|
|
// documentation and/or other materials provided with the distribution;
|
|
// neither the name of the copyright holders nor the names of its
|
|
// contributors may be used to endorse or promote products derived from
|
|
// this software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
//
|
|
// Authors: Gabe Black
|
|
|
|
def format ArmDataProcReg() {{
|
|
pclr = '''
|
|
return new %(className)ssRegPclr(machInst, %(dest)s,
|
|
%(op1)s, rm, imm5,
|
|
type);
|
|
'''
|
|
instDecode = '''
|
|
case %(opcode)#x:
|
|
if (immShift) {
|
|
if (setCc) {
|
|
if (%(dest)s == INTREG_PC) {
|
|
%(pclr)s
|
|
} else {
|
|
return new %(className)sRegCc(machInst, %(dest)s,
|
|
%(op1)s, rm, imm5, type);
|
|
}
|
|
} else {
|
|
return new %(className)sReg(machInst, %(dest)s, %(op1)s,
|
|
rm, imm5, type);
|
|
}
|
|
} else {
|
|
if (setCc) {
|
|
return new %(className)sRegRegCc(machInst, %(dest)s,
|
|
%(op1)s, rm, rs, type);
|
|
} else {
|
|
return new %(className)sRegReg(machInst, %(dest)s,
|
|
%(op1)s, rm, rs, type);
|
|
}
|
|
}
|
|
break;
|
|
'''
|
|
|
|
def instCode(opcode, mnem, useDest = True, useOp1 = True):
|
|
global pclr
|
|
if useDest:
|
|
dest = "rd"
|
|
else:
|
|
dest = "INTREG_ZERO"
|
|
if useOp1:
|
|
op1 = "rn"
|
|
else:
|
|
op1 = "INTREG_ZERO"
|
|
global instDecode, pclrCode
|
|
substDict = { "className": mnem.capitalize(),
|
|
"opcode": opcode,
|
|
"dest": dest,
|
|
"op1": op1 }
|
|
if useDest:
|
|
substDict["pclr"] = pclr % substDict
|
|
else:
|
|
substDict["pclr"] = ""
|
|
return instDecode % substDict
|
|
|
|
decode_block = '''
|
|
{
|
|
const bool immShift = (bits(machInst, 4) == 0);
|
|
const bool setCc = (bits(machInst, 20) == 1);
|
|
const uint32_t imm5 = bits(machInst, 11, 7);
|
|
const ArmShiftType type = (ArmShiftType)(uint32_t)bits(machInst, 6, 5);
|
|
const IntRegIndex rd = (IntRegIndex)(uint32_t)RD;
|
|
const IntRegIndex rn = (IntRegIndex)(uint32_t)RN;
|
|
const IntRegIndex rm = (IntRegIndex)(uint32_t)RM;
|
|
const IntRegIndex rs = (IntRegIndex)(uint32_t)RS;
|
|
switch (OPCODE) {
|
|
'''
|
|
decode_block += instCode(0x0, "and")
|
|
decode_block += instCode(0x1, "eor")
|
|
decode_block += instCode(0x2, "sub")
|
|
decode_block += instCode(0x3, "rsb")
|
|
decode_block += instCode(0x4, "add")
|
|
decode_block += instCode(0x5, "adc")
|
|
decode_block += instCode(0x6, "sbc")
|
|
decode_block += instCode(0x7, "rsc")
|
|
decode_block += instCode(0x8, "tst", useDest = False)
|
|
decode_block += instCode(0x9, "teq", useDest = False)
|
|
decode_block += instCode(0xa, "cmp", useDest = False)
|
|
decode_block += instCode(0xb, "cmn", useDest = False)
|
|
decode_block += instCode(0xc, "orr")
|
|
decode_block += instCode(0xd, "mov", useOp1 = False)
|
|
decode_block += instCode(0xe, "bic")
|
|
decode_block += instCode(0xf, "mvn", useOp1 = False)
|
|
decode_block += '''
|
|
default:
|
|
return new Unknown(machInst);
|
|
}
|
|
}
|
|
'''
|
|
}};
|
|
|
|
def format ArmPackUnpackSatReverse() {{
|
|
decode_block = '''
|
|
{
|
|
const uint32_t op1 = bits(machInst, 22, 20);
|
|
const uint32_t a = bits(machInst, 19, 16);
|
|
const uint32_t op2 = bits(machInst, 7, 5);
|
|
if (bits(op2, 0) == 0) {
|
|
const IntRegIndex rn =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 3, 0);
|
|
const IntRegIndex rd =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 15, 12);
|
|
const uint32_t satImm = bits(machInst, 20, 16);
|
|
const uint32_t imm = bits(machInst, 11, 7);
|
|
const ArmShiftType type =
|
|
(ArmShiftType)(uint32_t)bits(machInst, 6, 5);
|
|
if (op1 == 0) {
|
|
return new WarnUnimplemented("pkh", machInst);
|
|
} else if (bits(op1, 2, 1) == 1) {
|
|
return new Ssat(machInst, rd, satImm + 1, rn, imm, type);
|
|
} else if (bits(op1, 2, 1) == 3) {
|
|
return new Usat(machInst, rd, satImm, rn, imm, type);
|
|
}
|
|
return new Unknown(machInst);
|
|
}
|
|
switch (op1) {
|
|
case 0x0:
|
|
if (op2 == 0x3) {
|
|
const IntRegIndex rn =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 19, 16);
|
|
const IntRegIndex rd =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 15, 12);
|
|
const IntRegIndex rm =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 3, 0);
|
|
const uint32_t rotation =
|
|
(uint32_t)bits(machInst, 11, 10) << 3;
|
|
if (a == 0xf) {
|
|
return new Sxtb16(machInst, rd, rotation, rm);
|
|
} else {
|
|
return new Sxtab16(machInst, rd, rn, rm, rotation);
|
|
}
|
|
} else if (op2 == 0x5) {
|
|
return new WarnUnimplemented("sel", machInst);
|
|
}
|
|
break;
|
|
case 0x2:
|
|
if (op2 == 0x1) {
|
|
const IntRegIndex rn =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 3, 0);
|
|
const IntRegIndex rd =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 15, 12);
|
|
const uint32_t satImm = bits(machInst, 20, 16);
|
|
return new Ssat16(machInst, rd, satImm + 1, rn);
|
|
} else if (op2 == 0x3) {
|
|
const IntRegIndex rn =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 19, 16);
|
|
const IntRegIndex rd =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 15, 12);
|
|
const IntRegIndex rm =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 3, 0);
|
|
const uint32_t rotation =
|
|
(uint32_t)bits(machInst, 11, 10) << 3;
|
|
if (a == 0xf) {
|
|
return new Sxtb(machInst, rd, rotation, rm);
|
|
} else {
|
|
return new Sxtab(machInst, rd, rn, rm, rotation);
|
|
}
|
|
}
|
|
break;
|
|
case 0x3:
|
|
if (op2 == 0x1) {
|
|
IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
|
|
IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
|
|
return new Rev(machInst, rd, rm);
|
|
} else if (op2 == 0x3) {
|
|
const IntRegIndex rn =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 19, 16);
|
|
const IntRegIndex rd =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 15, 12);
|
|
const IntRegIndex rm =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 3, 0);
|
|
const uint32_t rotation =
|
|
(uint32_t)bits(machInst, 11, 10) << 3;
|
|
if (a == 0xf) {
|
|
return new Sxth(machInst, rd, rotation, rm);
|
|
} else {
|
|
return new Sxtah(machInst, rd, rn, rm, rotation);
|
|
}
|
|
} else if (op2 == 0x5) {
|
|
IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
|
|
IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
|
|
return new Rev16(machInst, rd, rm);
|
|
}
|
|
break;
|
|
case 0x4:
|
|
if (op2 == 0x3) {
|
|
const IntRegIndex rn =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 19, 16);
|
|
const IntRegIndex rd =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 15, 12);
|
|
const IntRegIndex rm =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 3, 0);
|
|
const uint32_t rotation =
|
|
(uint32_t)bits(machInst, 11, 10) << 3;
|
|
if (a == 0xf) {
|
|
return new Uxtb16(machInst, rd, rotation, rm);
|
|
} else {
|
|
return new Uxtab16(machInst, rd, rn, rm, rotation);
|
|
}
|
|
}
|
|
break;
|
|
case 0x6:
|
|
if (op2 == 0x1) {
|
|
const IntRegIndex rn =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 3, 0);
|
|
const IntRegIndex rd =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 15, 12);
|
|
const uint32_t satImm = bits(machInst, 20, 16);
|
|
return new Usat16(machInst, rd, satImm, rn);
|
|
} else if (op2 == 0x3) {
|
|
const IntRegIndex rn =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 19, 16);
|
|
const IntRegIndex rd =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 15, 12);
|
|
const IntRegIndex rm =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 3, 0);
|
|
const uint32_t rotation =
|
|
(uint32_t)bits(machInst, 11, 10) << 3;
|
|
if (a == 0xf) {
|
|
return new Uxtb(machInst, rd, rotation, rm);
|
|
} else {
|
|
return new Uxtab(machInst, rd, rn, rm, rotation);
|
|
}
|
|
}
|
|
break;
|
|
case 0x7:
|
|
if (op2 == 0x1) {
|
|
return new WarnUnimplemented("rbit", machInst);
|
|
} else if (op2 == 0x3) {
|
|
const IntRegIndex rn =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 19, 16);
|
|
const IntRegIndex rd =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 15, 12);
|
|
const IntRegIndex rm =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 3, 0);
|
|
const uint32_t rotation =
|
|
(uint32_t)bits(machInst, 11, 10) << 3;
|
|
if (a == 0xf) {
|
|
return new Uxth(machInst, rd, rotation, rm);
|
|
} else {
|
|
return new Uxtah(machInst, rd, rn, rm, rotation);
|
|
}
|
|
} else if (op2 == 0x5) {
|
|
IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
|
|
IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
|
|
return new Revsh(machInst, rd, rm);
|
|
}
|
|
break;
|
|
}
|
|
return new Unknown(machInst);
|
|
}
|
|
'''
|
|
}};
|
|
|
|
def format ArmParallelAddSubtract() {{
|
|
decode_block='''
|
|
{
|
|
const uint32_t op1 = bits(machInst, 21, 20);
|
|
const uint32_t op2 = bits(machInst, 7, 5);
|
|
const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
|
|
const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
|
|
const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
|
|
if (bits(machInst, 22) == 0) {
|
|
switch (op1) {
|
|
case 0x1:
|
|
switch (op2) {
|
|
case 0x0:
|
|
return new Sadd16RegCc(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x1:
|
|
return new SasxRegCc(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x2:
|
|
return new SsaxRegCc(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x3:
|
|
return new Ssub16RegCc(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x4:
|
|
return new Sadd8RegCc(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x7:
|
|
return new Ssub8RegCc(machInst, rd, rn, rm, 0, LSL);
|
|
}
|
|
break;
|
|
case 0x2:
|
|
switch (op2) {
|
|
case 0x0:
|
|
return new Qadd16Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x1:
|
|
return new QasxReg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x2:
|
|
return new QsaxReg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x3:
|
|
return new Qsub16Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x4:
|
|
return new Qadd8Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x7:
|
|
return new Qsub8Reg(machInst, rd, rn, rm, 0, LSL);
|
|
}
|
|
break;
|
|
case 0x3:
|
|
switch (op2) {
|
|
case 0x0:
|
|
return new Shadd16Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x1:
|
|
return new ShasxReg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x2:
|
|
return new ShsaxReg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x3:
|
|
return new Shsub16Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x4:
|
|
return new Shadd8Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x7:
|
|
return new Shsub8Reg(machInst, rd, rn, rm, 0, LSL);
|
|
}
|
|
break;
|
|
}
|
|
} else {
|
|
switch (op1) {
|
|
case 0x1:
|
|
switch (op2) {
|
|
case 0x0:
|
|
return new Uadd16RegCc(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x1:
|
|
return new UasxRegCc(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x2:
|
|
return new UsaxRegCc(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x3:
|
|
return new Usub16RegCc(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x4:
|
|
return new Uadd8RegCc(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x7:
|
|
return new Usub8RegCc(machInst, rd, rn, rm, 0, LSL);
|
|
}
|
|
break;
|
|
case 0x2:
|
|
switch (op2) {
|
|
case 0x0:
|
|
return new Uqadd16Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x1:
|
|
return new UqasxReg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x2:
|
|
return new UqsaxReg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x3:
|
|
return new Uqsub16Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x4:
|
|
return new Uqadd8Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x7:
|
|
return new Uqsub8Reg(machInst, rd, rn, rm, 0, LSL);
|
|
}
|
|
break;
|
|
case 0x3:
|
|
switch (op2) {
|
|
case 0x0:
|
|
return new Uhadd16Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x1:
|
|
return new UhasxReg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x2:
|
|
return new UhsaxReg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x3:
|
|
return new Uhsub16Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x4:
|
|
return new Uhadd8Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x7:
|
|
return new Uhsub8Reg(machInst, rd, rn, rm, 0, LSL);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return new Unknown(machInst);
|
|
}
|
|
'''
|
|
}};
|
|
|
|
def format ArmDataProcImm() {{
|
|
pclr = '''
|
|
return new %(className)ssImmPclr(machInst, %(dest)s,
|
|
%(op1)s, imm, false);
|
|
'''
|
|
adr = '''
|
|
return new AdrImm(machInst, %(dest)s, %(add)s,
|
|
imm, false);
|
|
'''
|
|
instDecode = '''
|
|
case %(opcode)#x:
|
|
if (setCc) {
|
|
if (%(pclrInst)s && %(dest)s == INTREG_PC) {
|
|
%(pclr)s
|
|
} else {
|
|
return new %(className)sImmCc(machInst, %(dest)s, %(op1)s,
|
|
imm, rotC);
|
|
}
|
|
} else {
|
|
if (%(adrInst)s && %(op1)s == INTREG_PC) {
|
|
%(adr)s
|
|
} else {
|
|
return new %(className)sImm(machInst, %(dest)s, %(op1)s,
|
|
imm, rotC);
|
|
}
|
|
}
|
|
break;
|
|
'''
|
|
|
|
def instCode(opcode, mnem, useDest = True, useOp1 = True):
|
|
global instDecode, pclr, adr
|
|
if useDest:
|
|
dest = "rd"
|
|
else:
|
|
dest = "INTREG_ZERO"
|
|
if useOp1:
|
|
op1 = "rn"
|
|
else:
|
|
op1 = "INTREG_ZERO"
|
|
substDict = { "className": mnem.capitalize(),
|
|
"opcode": opcode,
|
|
"dest": dest,
|
|
"op1": op1,
|
|
"adr": "",
|
|
"adrInst": "false" }
|
|
if useDest:
|
|
substDict["pclrInst"] = "true"
|
|
substDict["pclr"] = pclr % substDict
|
|
else:
|
|
substDict["pclrInst"] = "false"
|
|
substDict["pclr"] = ""
|
|
return instDecode % substDict
|
|
|
|
def adrCode(opcode, mnem, add="1"):
|
|
global instDecode, pclr, adr
|
|
substDict = { "className": mnem.capitalize(),
|
|
"opcode": opcode,
|
|
"dest": "rd",
|
|
"op1": "rn",
|
|
"add": add,
|
|
"pclrInst": "true",
|
|
"adrInst": "true" }
|
|
substDict["pclr"] = pclr % substDict
|
|
substDict["adr"] = adr % substDict
|
|
return instDecode % substDict
|
|
|
|
decode_block = '''
|
|
{
|
|
const bool setCc = (bits(machInst, 20) == 1);
|
|
const uint32_t unrotated = bits(machInst, 7, 0);
|
|
const uint32_t rotation = (bits(machInst, 11, 8) << 1);
|
|
const bool rotC = (rotation != 0);
|
|
const uint32_t imm = rotate_imm(unrotated, rotation);
|
|
const IntRegIndex rd = (IntRegIndex)(uint32_t)RD;
|
|
const IntRegIndex rn = (IntRegIndex)(uint32_t)RN;
|
|
switch (OPCODE) {
|
|
'''
|
|
decode_block += instCode(0x0, "and")
|
|
decode_block += instCode(0x1, "eor")
|
|
decode_block += adrCode(0x2, "sub", add="(IntRegIndex)0")
|
|
decode_block += instCode(0x3, "rsb")
|
|
decode_block += adrCode(0x4, "add", add="(IntRegIndex)1")
|
|
decode_block += instCode(0x5, "adc")
|
|
decode_block += instCode(0x6, "sbc")
|
|
decode_block += instCode(0x7, "rsc")
|
|
decode_block += instCode(0x8, "tst", useDest = False)
|
|
decode_block += instCode(0x9, "teq", useDest = False)
|
|
decode_block += instCode(0xa, "cmp", useDest = False)
|
|
decode_block += instCode(0xb, "cmn", useDest = False)
|
|
decode_block += instCode(0xc, "orr")
|
|
decode_block += instCode(0xd, "mov", useOp1 = False)
|
|
decode_block += instCode(0xe, "bic")
|
|
decode_block += instCode(0xf, "mvn", useOp1 = False)
|
|
decode_block += '''
|
|
default:
|
|
return new Unknown(machInst);
|
|
}
|
|
}
|
|
'''
|
|
}};
|
|
|
|
def format ArmSatAddSub() {{
|
|
decode_block = '''
|
|
{
|
|
IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
|
|
IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
|
|
IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
|
|
switch (OPCODE) {
|
|
case 0x8:
|
|
return new QaddRegCc(machInst, rd, rm, rn, 0, LSL);
|
|
case 0x9:
|
|
return new QsubRegCc(machInst, rd, rm, rn, 0, LSL);
|
|
case 0xa:
|
|
return new QdaddRegCc(machInst, rd, rm, rn, 0, LSL);
|
|
case 0xb:
|
|
return new QdsubRegCc(machInst, rd, rm, rn, 0, LSL);
|
|
default:
|
|
return new Unknown(machInst);
|
|
}
|
|
}
|
|
'''
|
|
}};
|
|
|
|
def format Thumb32DataProcReg() {{
|
|
decode_block = '''
|
|
{
|
|
const uint32_t op1 = bits(machInst, 23, 20);
|
|
const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
|
|
const uint32_t op2 = bits(machInst, 7, 4);
|
|
if (bits(op1, 3) != 1) {
|
|
if (op2 == 0) {
|
|
IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
|
|
IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
|
|
switch (bits(op1, 2, 0)) {
|
|
case 0x0:
|
|
return new MovRegReg(machInst, rd,
|
|
INTREG_ZERO, rn, rm, LSL);
|
|
case 0x1:
|
|
return new MovRegRegCc(machInst, rd,
|
|
INTREG_ZERO, rn, rm, LSL);
|
|
case 0x2:
|
|
return new MovRegReg(machInst, rd,
|
|
INTREG_ZERO, rn, rm, LSR);
|
|
case 0x3:
|
|
return new MovRegRegCc(machInst, rd,
|
|
INTREG_ZERO, rn, rm, LSR);
|
|
case 0x4:
|
|
return new MovRegReg(machInst, rd,
|
|
INTREG_ZERO, rn, rm, ASR);
|
|
case 0x5:
|
|
return new MovRegRegCc(machInst, rd,
|
|
INTREG_ZERO, rn, rm, ASR);
|
|
case 0x6:
|
|
return new MovRegReg(machInst, rd,
|
|
INTREG_ZERO, rn, rm, ROR);
|
|
case 0x7:
|
|
return new MovRegRegCc(machInst, rd,
|
|
INTREG_ZERO, rn, rm, ROR);
|
|
}
|
|
}
|
|
{
|
|
const IntRegIndex rd =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 11, 8);
|
|
const IntRegIndex rm =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 3, 0);
|
|
const uint32_t rotation =
|
|
(uint32_t)bits(machInst, 5, 4) << 3;
|
|
switch (bits(op1, 2, 0)) {
|
|
case 0x0:
|
|
if (rn == 0xf) {
|
|
return new Sxth(machInst, rd, rotation, rm);
|
|
} else {
|
|
return new Sxtah(machInst, rd, rn, rm, rotation);
|
|
}
|
|
case 0x1:
|
|
if (rn == 0xf) {
|
|
return new Uxth(machInst, rd, rotation, rm);
|
|
} else {
|
|
return new Uxtah(machInst, rd, rn, rm, rotation);
|
|
}
|
|
case 0x2:
|
|
if (rn == 0xf) {
|
|
return new Sxtb16(machInst, rd, rotation, rm);
|
|
} else {
|
|
return new Sxtab16(machInst, rd, rn, rm, rotation);
|
|
}
|
|
case 0x3:
|
|
if (rn == 0xf) {
|
|
return new Uxtb16(machInst, rd, rotation, rm);
|
|
} else {
|
|
return new Uxtab16(machInst, rd, rn, rm, rotation);
|
|
}
|
|
case 0x4:
|
|
if (rn == 0xf) {
|
|
return new Sxtb(machInst, rd, rotation, rm);
|
|
} else {
|
|
return new Sxtab(machInst, rd, rn, rm, rotation);
|
|
}
|
|
case 0x5:
|
|
if (rn == 0xf) {
|
|
return new Uxtb(machInst, rd, rotation, rm);
|
|
} else {
|
|
return new Uxtab(machInst, rd, rn, rm, rotation);
|
|
}
|
|
default:
|
|
return new Unknown(machInst);
|
|
}
|
|
}
|
|
} else {
|
|
if (bits(op2, 3) == 0) {
|
|
const IntRegIndex rd =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 11, 8);
|
|
const IntRegIndex rm =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 3, 0);
|
|
if (bits(op2, 2) == 0x0) {
|
|
const uint32_t op1 = bits(machInst, 22, 20);
|
|
const uint32_t op2 = bits(machInst, 5, 4);
|
|
switch (op2) {
|
|
case 0x0:
|
|
switch (op1) {
|
|
case 0x1:
|
|
return new Sadd16RegCc(machInst, rd,
|
|
rn, rm, 0, LSL);
|
|
case 0x2:
|
|
return new SasxRegCc(machInst, rd,
|
|
rn, rm, 0, LSL);
|
|
case 0x6:
|
|
return new SsaxRegCc(machInst, rd,
|
|
rn, rm, 0, LSL);
|
|
case 0x5:
|
|
return new Ssub16RegCc(machInst, rd,
|
|
rn, rm, 0, LSL);
|
|
case 0x0:
|
|
return new Sadd8RegCc(machInst, rd,
|
|
rn, rm, 0, LSL);
|
|
case 0x4:
|
|
return new Ssub8RegCc(machInst, rd,
|
|
rn, rm, 0, LSL);
|
|
}
|
|
break;
|
|
case 0x1:
|
|
switch (op1) {
|
|
case 0x1:
|
|
return new Qadd16Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x2:
|
|
return new QasxReg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x6:
|
|
return new QsaxReg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x5:
|
|
return new Qsub16Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x0:
|
|
return new Qadd8Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x4:
|
|
return new Qsub8Reg(machInst, rd, rn, rm, 0, LSL);
|
|
}
|
|
break;
|
|
case 0x2:
|
|
switch (op1) {
|
|
case 0x1:
|
|
return new Shadd16Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x2:
|
|
return new ShasxReg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x6:
|
|
return new ShsaxReg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x5:
|
|
return new Shsub16Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x0:
|
|
return new Shadd8Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x4:
|
|
return new Shsub8Reg(machInst, rd, rn, rm, 0, LSL);
|
|
}
|
|
break;
|
|
}
|
|
} else {
|
|
const uint32_t op1 = bits(machInst, 22, 20);
|
|
const uint32_t op2 = bits(machInst, 5, 4);
|
|
switch (op2) {
|
|
case 0x0:
|
|
switch (op1) {
|
|
case 0x1:
|
|
return new Uadd16RegCc(machInst, rd,
|
|
rn, rm, 0, LSL);
|
|
case 0x2:
|
|
return new UasxRegCc(machInst, rd,
|
|
rn, rm, 0, LSL);
|
|
case 0x6:
|
|
return new UsaxRegCc(machInst, rd,
|
|
rn, rm, 0, LSL);
|
|
case 0x5:
|
|
return new Usub16RegCc(machInst, rd,
|
|
rn, rm, 0, LSL);
|
|
case 0x0:
|
|
return new Uadd8RegCc(machInst, rd,
|
|
rn, rm, 0, LSL);
|
|
case 0x4:
|
|
return new Usub8RegCc(machInst, rd,
|
|
rn, rm, 0, LSL);
|
|
}
|
|
break;
|
|
case 0x1:
|
|
switch (op1) {
|
|
case 0x1:
|
|
return new Uqadd16Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x2:
|
|
return new UqasxReg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x6:
|
|
return new UqsaxReg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x5:
|
|
return new Uqsub16Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x0:
|
|
return new Uqadd8Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x4:
|
|
return new Uqsub8Reg(machInst, rd, rn, rm, 0, LSL);
|
|
}
|
|
break;
|
|
case 0x2:
|
|
switch (op1) {
|
|
case 0x1:
|
|
return new Uhadd16Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x2:
|
|
return new UhasxReg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x6:
|
|
return new UhsaxReg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x5:
|
|
return new Uhsub16Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x0:
|
|
return new Uhadd8Reg(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x4:
|
|
return new Uhsub8Reg(machInst, rd, rn, rm, 0, LSL);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
} else if (bits(op1, 3, 2) == 0x2 && bits(op2, 3, 2) == 0x2) {
|
|
const uint32_t op1 = bits(machInst, 21, 20);
|
|
const uint32_t op2 = bits(machInst, 5, 4);
|
|
switch (op1) {
|
|
case 0x0:
|
|
{
|
|
IntRegIndex rd =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 11, 8);
|
|
IntRegIndex rm =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 3, 0);
|
|
switch (op2) {
|
|
case 0x0:
|
|
return new QaddRegCc(machInst, rd,
|
|
rm, rn, 0, LSL);
|
|
case 0x1:
|
|
return new QdaddRegCc(machInst, rd,
|
|
rm, rn, 0, LSL);
|
|
case 0x2:
|
|
return new QsubRegCc(machInst, rd,
|
|
rm, rn, 0, LSL);
|
|
case 0x3:
|
|
return new QdsubRegCc(machInst, rd,
|
|
rm, rn, 0, LSL);
|
|
}
|
|
}
|
|
break;
|
|
case 0x1:
|
|
{
|
|
IntRegIndex rd =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 11, 8);
|
|
IntRegIndex rm = rn;
|
|
switch (op2) {
|
|
case 0x0:
|
|
return new Rev(machInst, rd, rm);
|
|
case 0x1:
|
|
return new Rev16(machInst, rd, rm);
|
|
case 0x2:
|
|
return new WarnUnimplemented("rbit", machInst);
|
|
case 0x3:
|
|
return new Revsh(machInst, rd, rm);
|
|
}
|
|
}
|
|
break;
|
|
case 0x2:
|
|
if (op2 == 0) {
|
|
return new WarnUnimplemented("sel", machInst);
|
|
}
|
|
break;
|
|
case 0x3:
|
|
if (op2 == 0) {
|
|
return new WarnUnimplemented("clz", machInst);
|
|
}
|
|
}
|
|
}
|
|
return new Unknown(machInst);
|
|
}
|
|
}
|
|
'''
|
|
}};
|
|
|
|
def format Thumb16ShiftAddSubMoveCmp() {{
|
|
decode_block = '''
|
|
{
|
|
const uint32_t imm5 = bits(machInst, 10, 6);
|
|
const uint32_t imm3 = bits(machInst, 8, 6);
|
|
const uint32_t imm8 = bits(machInst, 7, 0);
|
|
const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 2, 0);
|
|
const IntRegIndex rd8 = (IntRegIndex)(uint32_t)bits(machInst, 10, 8);
|
|
const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 5, 3);
|
|
const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 8, 6);
|
|
switch (bits(machInst, 13, 11)) {
|
|
case 0x0: // lsl
|
|
return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, LSL);
|
|
case 0x1: // lsr
|
|
return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, LSR);
|
|
case 0x2: // asr
|
|
return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, ASR);
|
|
case 0x3:
|
|
switch (bits(machInst, 10, 9)) {
|
|
case 0x0:
|
|
return new AddRegCc(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x1:
|
|
return new SubRegCc(machInst, rd, rn, rm, 0, LSL);
|
|
case 0x2:
|
|
return new AddImmCc(machInst, rd, rn, imm3, true);
|
|
case 0x3:
|
|
return new SubImmCc(machInst, rd, rn, imm3, true);
|
|
}
|
|
case 0x4:
|
|
return new MovImmCc(machInst, rd8, INTREG_ZERO, imm8, false);
|
|
case 0x5:
|
|
return new CmpImmCc(machInst, INTREG_ZERO, rd8, imm8, true);
|
|
case 0x6:
|
|
return new AddImmCc(machInst, rd8, rd8, imm8, true);
|
|
case 0x7:
|
|
return new SubImmCc(machInst, rd8, rd8, imm8, true);
|
|
}
|
|
}
|
|
'''
|
|
}};
|
|
|
|
def format Thumb16DataProcessing() {{
|
|
decode_block = '''
|
|
{
|
|
const IntRegIndex rdn = (IntRegIndex)(uint32_t)bits(machInst, 2, 0);
|
|
const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 5, 3);
|
|
switch (bits(machInst, 9, 6)) {
|
|
case 0x0:
|
|
return new AndRegCc(machInst, rdn, rdn, rm, 0, LSL);
|
|
case 0x1:
|
|
return new EorRegCc(machInst, rdn, rdn, rm, 0, LSL);
|
|
case 0x2: //lsl
|
|
return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, LSL);
|
|
case 0x3: //lsr
|
|
return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, LSR);
|
|
case 0x4: //asr
|
|
return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, ASR);
|
|
case 0x5:
|
|
return new AdcRegCc(machInst, rdn, rdn, rm, 0, LSL);
|
|
case 0x6:
|
|
return new SbcRegCc(machInst, rdn, rdn, rm, 0, LSL);
|
|
case 0x7: // ror
|
|
return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, ROR);
|
|
case 0x8:
|
|
return new TstRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
|
|
case 0x9:
|
|
return new RsbImmCc(machInst, rdn, rm, 0, true);
|
|
case 0xa:
|
|
return new CmpRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
|
|
case 0xb:
|
|
return new CmnRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
|
|
case 0xc:
|
|
return new OrrRegCc(machInst, rdn, rdn, rm, 0, LSL);
|
|
case 0xd:
|
|
return new MulCc(machInst, rdn, rm, rdn);
|
|
case 0xe:
|
|
return new BicRegCc(machInst, rdn, rdn, rm, 0, LSL);
|
|
case 0xf:
|
|
return new MvnRegCc(machInst, rdn, INTREG_ZERO, rm, 0, LSL);
|
|
}
|
|
}
|
|
'''
|
|
}};
|
|
|
|
def format Thumb16SpecDataAndBx() {{
|
|
decode_block = '''
|
|
{
|
|
const IntRegIndex rdn =
|
|
(IntRegIndex)(uint32_t)(bits(machInst, 2, 0) |
|
|
(bits(machInst, 7) << 3));
|
|
const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 6, 3);
|
|
switch (bits(machInst, 9, 8)) {
|
|
case 0x0:
|
|
return new AddReg(machInst, rdn, rdn, rm, 0, LSL);
|
|
case 0x1:
|
|
return new CmpRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
|
|
case 0x2:
|
|
return new MovReg(machInst, rdn, INTREG_ZERO, rm, 0, LSL);
|
|
case 0x3:
|
|
if (bits(machInst, 7) == 0) {
|
|
return new BxReg(machInst,
|
|
(IntRegIndex)(uint32_t)bits(machInst, 6, 3),
|
|
COND_UC);
|
|
} else {
|
|
return new BlxReg(machInst,
|
|
(IntRegIndex)(uint32_t)bits(machInst, 6, 3),
|
|
COND_UC);
|
|
}
|
|
}
|
|
}
|
|
'''
|
|
}};
|
|
|
|
def format Thumb16Adr() {{
|
|
decode_block = '''
|
|
{
|
|
const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 10, 8);
|
|
const uint32_t imm8 = bits(machInst, 7, 0) << 2;
|
|
return new AdrImm(machInst, rd, (IntRegIndex)1, imm8, false);
|
|
}
|
|
'''
|
|
}};
|
|
|
|
def format Thumb16AddSp() {{
|
|
decode_block = '''
|
|
{
|
|
const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 10, 8);
|
|
const uint32_t imm8 = bits(machInst, 7, 0) << 2;
|
|
return new AddImm(machInst, rd, INTREG_SP, imm8, true);
|
|
}
|
|
'''
|
|
}};
|
|
|
|
def format Thumb16Misc() {{
|
|
decode_block = '''
|
|
{
|
|
switch (bits(machInst, 11, 8)) {
|
|
case 0x0:
|
|
if (bits(machInst, 7)) {
|
|
return new SubImm(machInst, INTREG_SP, INTREG_SP,
|
|
bits(machInst, 6, 0) << 2, true);
|
|
} else {
|
|
return new AddImm(machInst, INTREG_SP, INTREG_SP,
|
|
bits(machInst, 6, 0) << 2, true);
|
|
}
|
|
case 0x1:
|
|
return new Cbz(machInst,
|
|
(bits(machInst, 9) << 6) |
|
|
(bits(machInst, 7, 3) << 1),
|
|
(IntRegIndex)(uint32_t)bits(machInst, 2, 0));
|
|
case 0x2:
|
|
{
|
|
const IntRegIndex rd =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 2, 0);
|
|
const IntRegIndex rm =
|
|
(IntRegIndex)(uint32_t)bits(machInst, 5, 3);
|
|
switch (bits(machInst, 7, 6)) {
|
|
case 0x0:
|
|
return new Sxth(machInst, rd, 0, rm);
|
|
case 0x1:
|
|
return new Sxtb(machInst, rd, 0, rm);
|
|
case 0x2:
|
|
return new Uxth(machInst, rd, 0, rm);
|
|
case 0x3:
|
|
return new Uxtb(machInst, rd, 0, rm);
|
|
}
|
|
}
|
|
case 0x3:
|
|
return new Cbz(machInst,
|
|
(bits(machInst, 9) << 6) |
|
|
(bits(machInst, 7, 3) << 1),
|
|
(IntRegIndex)(uint32_t)bits(machInst, 2, 0));
|
|
case 0x4:
|
|
case 0x5:
|
|
{
|
|
const uint32_t m = bits(machInst, 8);
|
|
const uint32_t regList = bits(machInst, 7, 0) | (m << 14);
|
|
return new LdmStm(machInst, INTREG_SP, false, false, false,
|
|
true, false, regList);
|
|
}
|
|
case 0x6:
|
|
{
|
|
const uint32_t opBits = bits(machInst, 7, 5);
|
|
if (opBits == 2) {
|
|
return new WarnUnimplemented("setend", machInst);
|
|
} else if (opBits == 3) {
|
|
return new WarnUnimplemented("cps", machInst);
|
|
}
|
|
}
|
|
case 0x9:
|
|
return new Cbnz(machInst,
|
|
(bits(machInst, 9) << 6) |
|
|
(bits(machInst, 7, 3) << 1),
|
|
(IntRegIndex)(uint32_t)bits(machInst, 2, 0));
|
|
case 0xa:
|
|
{
|
|
IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 2, 0);
|
|
IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 5, 3);
|
|
switch (bits(machInst, 7, 6)) {
|
|
case 0x0:
|
|
return new Rev(machInst, rd, rm);
|
|
case 0x1:
|
|
return new Rev16(machInst, rd, rm);
|
|
case 0x3:
|
|
return new Revsh(machInst, rd, rm);
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case 0xb:
|
|
return new Cbnz(machInst,
|
|
(bits(machInst, 9) << 6) |
|
|
(bits(machInst, 7, 3) << 1),
|
|
(IntRegIndex)(uint32_t)bits(machInst, 2, 0));
|
|
case 0xc:
|
|
case 0xd:
|
|
{
|
|
const uint32_t p = bits(machInst, 8);
|
|
const uint32_t regList = bits(machInst, 7, 0) | (p << 15);
|
|
return new LdmStm(machInst, INTREG_SP, true, true, false,
|
|
true, true, regList);
|
|
}
|
|
case 0xe:
|
|
return new WarnUnimplemented("bkpt", machInst);
|
|
case 0xf:
|
|
if (bits(machInst, 3, 0) != 0)
|
|
return new WarnUnimplemented("it", machInst);
|
|
switch (bits(machInst, 7, 4)) {
|
|
case 0x0:
|
|
return new WarnUnimplemented("nop", machInst);
|
|
case 0x1:
|
|
return new WarnUnimplemented("yield", machInst);
|
|
case 0x2:
|
|
return new WarnUnimplemented("wfe", machInst);
|
|
case 0x3:
|
|
return new WarnUnimplemented("wfi", machInst);
|
|
case 0x4:
|
|
return new WarnUnimplemented("sev", machInst);
|
|
default:
|
|
return new WarnUnimplemented("unallocated_hint", machInst);
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return new Unknown(machInst);
|
|
}
|
|
'''
|
|
}};
|
|
|
|
def format Thumb32DataProcModImm() {{
|
|
|
|
def decInst(mnem, dest="rd", op1="rn"):
|
|
return '''
|
|
if (s) {
|
|
return new %(mnem)sImmCc(machInst, %(dest)s,
|
|
%(op1)s, imm, rotC);
|
|
} else {
|
|
return new %(mnem)sImm(machInst, %(dest)s,
|
|
%(op1)s, imm, rotC);
|
|
}
|
|
''' % {"mnem" : mnem, "dest" : dest, "op1" : op1}
|
|
|
|
decode_block = '''
|
|
{
|
|
const uint32_t op = bits(machInst, 24, 21);
|
|
const bool s = (bits(machInst, 20) == 1);
|
|
const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
|
|
const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
|
|
const uint32_t ctrlImm = bits(machInst.instBits, 26) << 3 |
|
|
bits(machInst, 14, 12);
|
|
const bool rotC = ctrlImm > 3;
|
|
const uint32_t dataImm = bits(machInst, 7, 0);
|
|
const uint32_t imm = modified_imm(ctrlImm, dataImm);
|
|
switch (op) {
|
|
case 0x0:
|
|
if (rd == INTREG_PC) {
|
|
%(tst)s
|
|
} else {
|
|
%(and)s
|
|
}
|
|
case 0x1:
|
|
%(bic)s
|
|
case 0x2:
|
|
if (rn == INTREG_PC) {
|
|
%(mov)s
|
|
} else {
|
|
%(orr)s
|
|
}
|
|
case 0x3:
|
|
if (rn == INTREG_PC) {
|
|
%(mvn)s
|
|
} else {
|
|
%(orn)s
|
|
}
|
|
case 0x4:
|
|
if (rd == INTREG_PC) {
|
|
%(teq)s
|
|
} else {
|
|
%(eor)s
|
|
}
|
|
case 0x8:
|
|
if (rd == INTREG_PC) {
|
|
%(cmn)s
|
|
} else {
|
|
%(add)s
|
|
}
|
|
case 0xa:
|
|
%(adc)s
|
|
case 0xb:
|
|
%(sbc)s
|
|
case 0xd:
|
|
if (rd == INTREG_PC) {
|
|
%(cmp)s
|
|
} else {
|
|
%(sub)s
|
|
}
|
|
case 0xe:
|
|
%(rsb)s
|
|
default:
|
|
return new Unknown(machInst);
|
|
}
|
|
}
|
|
''' % {
|
|
"tst" : decInst("Tst", "INTREG_ZERO"),
|
|
"and" : decInst("And"),
|
|
"bic" : decInst("Bic"),
|
|
"mov" : decInst("Mov", op1="INTREG_ZERO"),
|
|
"orr" : decInst("Orr"),
|
|
"mvn" : decInst("Mvn", op1="INTREG_ZERO"),
|
|
"orn" : decInst("Orn"),
|
|
"teq" : decInst("Teq", dest="INTREG_ZERO"),
|
|
"eor" : decInst("Eor"),
|
|
"cmn" : decInst("Cmn", dest="INTREG_ZERO"),
|
|
"add" : decInst("Add"),
|
|
"adc" : decInst("Adc"),
|
|
"sbc" : decInst("Sbc"),
|
|
"cmp" : decInst("Cmp", dest="INTREG_ZERO"),
|
|
"sub" : decInst("Sub"),
|
|
"rsb" : decInst("Rsb")
|
|
}
|
|
}};
|
|
|
|
def format Thumb32DataProcPlainBin() {{
|
|
decode_block = '''
|
|
{
|
|
const uint32_t op = bits(machInst, 24, 20);
|
|
const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
|
|
const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
|
|
switch (op) {
|
|
case 0x0:
|
|
{
|
|
const uint32_t imm = bits(machInst, 7, 0) |
|
|
(bits(machInst, 14, 12) << 8) |
|
|
(bits(machInst, 26) << 11);
|
|
if (rn == 0xf) {
|
|
return new AdrImm(machInst, rd, (IntRegIndex)1,
|
|
imm, false);
|
|
} else {
|
|
return new AddImm(machInst, rd, rn, imm, true);
|
|
}
|
|
}
|
|
case 0x4:
|
|
{
|
|
const uint32_t imm = bits(machInst, 7, 0) |
|
|
(bits(machInst, 14, 12) << 8) |
|
|
(bits(machInst, 26) << 11) |
|
|
(bits(machInst, 19, 16) << 12);
|
|
return new MovImm(machInst, rd, INTREG_ZERO, imm, true);
|
|
}
|
|
case 0xa:
|
|
{
|
|
const uint32_t imm = bits(machInst, 7, 0) |
|
|
(bits(machInst, 14, 12) << 8) |
|
|
(bits(machInst, 26) << 11);
|
|
if (rn == 0xf) {
|
|
return new AdrImm(machInst, rd, (IntRegIndex)0,
|
|
imm, false);
|
|
} else {
|
|
return new SubImm(machInst, rd, rn, imm, true);
|
|
}
|
|
}
|
|
case 0xc:
|
|
{
|
|
const uint32_t imm = bits(machInst, 7, 0) |
|
|
(bits(machInst, 14, 12) << 8) |
|
|
(bits(machInst, 26) << 11) |
|
|
(bits(machInst, 19, 16) << 12);
|
|
return new MovtImm(machInst, rd, rd, imm, true);
|
|
}
|
|
case 0x12:
|
|
if (!(bits(machInst, 14, 12) || bits(machInst, 7, 6))) {
|
|
const uint32_t satImm = bits(machInst, 4, 0);
|
|
return new Ssat16(machInst, rd, satImm + 1, rn);
|
|
}
|
|
// Fall through on purpose...
|
|
case 0x10:
|
|
{
|
|
const uint32_t satImm = bits(machInst, 4, 0);
|
|
const uint32_t imm = bits(machInst, 7, 6) |
|
|
(bits(machInst, 14, 12) << 2);
|
|
const ArmShiftType type =
|
|
(ArmShiftType)(uint32_t)bits(machInst, 21, 20);
|
|
return new Ssat(machInst, rd, satImm + 1, rn, imm, type);
|
|
}
|
|
case 0x14:
|
|
return new WarnUnimplemented("sbfx", machInst);
|
|
case 0x16:
|
|
if (rn == 0xf) {
|
|
return new WarnUnimplemented("bfc", machInst);
|
|
} else {
|
|
return new WarnUnimplemented("bfi", machInst);
|
|
}
|
|
case 0x1a:
|
|
if (!(bits(machInst, 14, 12) || bits(machInst, 7, 6))) {
|
|
const uint32_t satImm = bits(machInst, 4, 0);
|
|
return new Usat16(machInst, rd, satImm, rn);
|
|
}
|
|
// Fall through on purpose...
|
|
case 0x18:
|
|
{
|
|
const uint32_t satImm = bits(machInst, 4, 0);
|
|
const uint32_t imm = bits(machInst, 7, 6) |
|
|
(bits(machInst, 14, 12) << 2);
|
|
const ArmShiftType type =
|
|
(ArmShiftType)(uint32_t)bits(machInst, 21, 20);
|
|
return new Usat(machInst, rd, satImm, rn, imm, type);
|
|
}
|
|
case 0x1c:
|
|
return new WarnUnimplemented("ubfx", machInst);
|
|
default:
|
|
return new Unknown(machInst);
|
|
}
|
|
}
|
|
'''
|
|
}};
|
|
|
|
def format Thumb32DataProcShiftReg() {{
|
|
|
|
def decInst(mnem, dest="rd", op1="rn"):
|
|
return '''
|
|
if (s) {
|
|
return new %(mnem)sRegCc(machInst, %(dest)s,
|
|
%(op1)s, rm, amt, type);
|
|
} else {
|
|
return new %(mnem)sReg(machInst, %(dest)s,
|
|
%(op1)s, rm, amt, type);
|
|
}
|
|
''' % {"mnem" : mnem, "dest" : dest, "op1" : op1}
|
|
|
|
decode_block = '''
|
|
{
|
|
const uint32_t op = bits(machInst, 24, 21);
|
|
const bool s = (bits(machInst, 20) == 1);
|
|
const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
|
|
const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
|
|
const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
|
|
const uint32_t amt = (bits(machInst, 14, 12) << 2) |
|
|
bits(machInst, 7, 6);
|
|
const ArmShiftType type = (ArmShiftType)(uint32_t)bits(machInst, 5, 4);
|
|
switch (op) {
|
|
case 0x0:
|
|
if (rd == INTREG_PC) {
|
|
%(tst)s
|
|
} else {
|
|
%(and)s
|
|
}
|
|
case 0x1:
|
|
%(bic)s
|
|
case 0x2:
|
|
if (rn == INTREG_PC) {
|
|
%(mov)s
|
|
} else {
|
|
%(orr)s
|
|
}
|
|
case 0x3:
|
|
if (rn == INTREG_PC) {
|
|
%(mvn)s
|
|
} else {
|
|
%(orn)s
|
|
}
|
|
case 0x4:
|
|
if (rd == INTREG_PC) {
|
|
%(teq)s
|
|
} else {
|
|
%(eor)s
|
|
}
|
|
case 0x6:
|
|
return new WarnUnimplemented("pkh", machInst);
|
|
case 0x8:
|
|
if (rd == INTREG_PC) {
|
|
%(cmn)s
|
|
} else {
|
|
%(add)s
|
|
}
|
|
case 0xa:
|
|
%(adc)s
|
|
case 0xb:
|
|
%(sbc)s
|
|
case 0xd:
|
|
if (rd == INTREG_PC) {
|
|
%(cmp)s
|
|
} else {
|
|
%(sub)s
|
|
}
|
|
case 0xe:
|
|
%(rsb)s
|
|
default:
|
|
return new Unknown(machInst);
|
|
}
|
|
}
|
|
''' % {
|
|
"tst" : decInst("Tst", "INTREG_ZERO"),
|
|
"and" : decInst("And"),
|
|
"bic" : decInst("Bic"),
|
|
"mov" : decInst("Mov", op1="INTREG_ZERO"),
|
|
"orr" : decInst("Orr"),
|
|
"mvn" : decInst("Mvn", op1="INTREG_ZERO"),
|
|
"orn" : decInst("Orn"),
|
|
"teq" : decInst("Teq", "INTREG_ZERO"),
|
|
"eor" : decInst("Eor"),
|
|
"cmn" : decInst("Cmn", "INTREG_ZERO"),
|
|
"add" : decInst("Add"),
|
|
"adc" : decInst("Adc"),
|
|
"sbc" : decInst("Sbc"),
|
|
"cmp" : decInst("Cmp", "INTREG_ZERO"),
|
|
"sub" : decInst("Sub"),
|
|
"rsb" : decInst("Rsb")
|
|
}
|
|
}};
|