blob: 3234497c2cbae2f2206901dde19192e7e3a447a5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2010 Nokia and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Nokia - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.debug.edc.tests;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.debug.edc.IJumpToAddress;
import org.eclipse.cdt.debug.edc.JumpToAddress;
import org.eclipse.cdt.debug.edc.disassembler.IDisassembledInstruction;
import org.eclipse.cdt.debug.edc.disassembler.IDisassembler.IDisassemblerOptions;
import org.eclipse.cdt.debug.edc.internal.arm.disassembler.DisassemblerARM;
import org.eclipse.cdt.debug.edc.internal.arm.disassembler.DisassemblerARM.IDisassemblerOptionsARM;
import org.eclipse.cdt.debug.edc.internal.arm.disassembler.InstructionParserARM;
import org.eclipse.cdt.utils.Addr32;
import org.eclipse.core.runtime.CoreException;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* Unit test for ARM disassembler.
*/
public class TestDisassemblerARM {
static Map<String, Object> armOptions = null;
static Map<String, Object> thumbOptions = null;
static DisassemblerARM sDisassembler;
/**
* Set up.
*/
@BeforeClass
public static void beforeClass() {
/*
* set up common disassembler options.
*/
armOptions = new HashMap<String, Object>();
armOptions.put(IDisassemblerOptions.MNEMONICS_SHOW_ADDRESS, true);
armOptions.put(IDisassemblerOptions.MNEMONICS_SHOW_BYTES, true);
armOptions.put(IDisassemblerOptionsARM.DISASSEMBLER_MODE, InstructionParserARM.DISASSEMBLER_MODE_ARM);
armOptions.put(IDisassemblerOptionsARM.ENDIAN_MODE, InstructionParserARM.BIG_ENDIAN_MODE);
thumbOptions = new HashMap<String, Object>();
thumbOptions.put(IDisassemblerOptions.MNEMONICS_SHOW_ADDRESS, true);
thumbOptions.put(IDisassemblerOptions.MNEMONICS_SHOW_BYTES, true);
thumbOptions.put(IDisassemblerOptionsARM.DISASSEMBLER_MODE, InstructionParserARM.DISASSEMBLER_MODE_THUMB);
thumbOptions.put(IDisassemblerOptionsARM.ENDIAN_MODE, InstructionParserARM.BIG_ENDIAN_MODE);
sDisassembler = new DisassemblerARM();
}
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
/**
* Test for ARM v5 instructions.
*/
@Test
public void testArmv5Instructions() {
System.out.println("\n===================== ARMv5 ========================\n");
String[] insts = { "E0 A1 00 02", "adc r0,r1,r2", "E2 81 00 01", "add r0,r1,#0x1", "E0 01 00 02",
"and r0,r1,r2", "EA FF FF FE", "b 0x0", "EB FF FF FE", "bl 0x0", "E1 C1 00 02", "bic r0,r1,r2",
"E1 20 01 70", "bkpt #0x10", "FA FF FF FE", "blx 0x0", "E1 2F FF 30", "blx r0", "E1 2F FF 10",
"bx r0", "EE 11 00 02", "cdp p0,0x1,cr0,cr1,cr2,0x0", "FE 11 00 02", "cdp2 p0,0x1,cr0,cr1,cr2,0x0",
"E1 6F 0F 11", "clz r0,r1", "E3 70 00 00", "cmn r0,#0x0", "E1 50 00 01", "cmp r0,r1", "E2 21 00 10",
"eor r0,r1,#0x10", "ED 91 00 00", "ldc p0,cr0,[r1,#0x0]", "FD 91 00 00", "ldc2 p0,cr0,[r1,#0x0]",
"E8 90 00 06", "ldmia r0,{r1,r2}", "E8 D0 00 06", "ldmia r0,{r1,r2}^", "E8 F0 00 06",
"ldmia r0!,{r1,r2}^", "E7 91 00 81", "ldr r0,[r1,r1,lsl #0x1]", "E5 D1 00 01", "ldrb r0,[r1,#0x1]",
"E4 F1 00 01", "ldrbt r0,[r1],#0x1", "E1 C1 00 D1", "ldrd r0,[r1,#0x1]", "E1 D1 00 B1",
"ldrh r0,[r1,#0x1]", "E1 D1 00 D1", "ldrsb r0,[r1,#0x1]", "E1 D1 00 F1", "ldrsh r0,[r1,#0x1]",
"E4 B1 00 01", "ldrt r0,[r1],#0x1", "EE 22 10 13", "mcr p0,0x1,r1,cr2,cr3", "FE 22 10 13",
"mcr2 p0,0x1,r1,cr2,cr3", "EC 42 10 13", "mcrr p0,0x1,r1,r2,cr3", "FC 42 10 13",
"mcrr2 p0,0x1,r1,r2,cr3", "E0 20 32 91", "mla r0,r1,r2,r3", "E3 A0 00 10", "mov r0,#0x10",
"EE 32 10 13", "mrc p0,0x1,r1,cr2,cr3", "FE 32 10 13", "mrc2 p0,0x1,r1,cr2,cr3", "EC 52 10 13",
"mrrc p0,0x1,r1,r2,cr3", "FC 52 10 13", "mrrc2 p0,0x1,r1,r2,cr3", "E1 0F 00 00", "mrs r0,cpsr",
"E3 29 F0 01", "msr cpsr_cf,#0x1", "E1 69 F0 00", "msr spsr_cf,r0", "E0 00 02 91", "mul r0,r1,r2",
"E1 E0 00 01", "mvn r0,r1", "E1 81 00 02", "orr r0,r1,r2", "F5 D0 F0 01", "pld [r0,#0x1]",
"E1 02 00 51", "qadd r0,r1,r2", "E1 42 00 51", "qdadd r0,r1,r2", "E1 62 00 51", "qdsub r0,r1,r2",
"E1 22 00 51", "qsub r0,r1,r2", "E0 61 00 02", "rsb r0,r1,r2", "E0 E1 00 02", "rsc r0,r1,r2",
"E0 C1 00 02", "sbc r0,r1,r2", "E1 00 32 81", "smlabb r0,r1,r2,r3", "E0 E1 03 92", "smlal r0,r1,r2,r3",
"E1 41 03 82", "smlalbb r0,r1,r2,r3", "E1 20 32 81", "smlawb r0,r1,r2,r3", "E1 60 02 81",
"smulbb r0,r1,r2", "E0 C1 03 92", "smull r0,r1,r2,r3", "E1 20 02 A1", "smulwb r0,r1,r2", "ED 81 10 00",
"stc p0,cr1,[r1,#0x0]", "FD 81 10 00", "stc2 p0,cr1,[r1,#0x0]", "E8 A0 00 06", "stmia r0!,{r1,r2}",
"E8 C0 00 06", "stmia r0,{r1,r2}^", "E4 81 00 01", "str r0,[r1],#0x1", "E4 C1 00 01",
"strb r0,[r1],#0x1", "E4 E1 00 01", "strbt r0,[r1],#0x1", "E0 C1 00 F1", "strd r0,[r1],#0x1",
"E0 C1 00 B1", "strh r0,[r1],#0x1", "E4 A1 00 01", "strt r0,[r1],#0x1", "E0 41 00 02", "sub r0,r1,r2",
"EF 00 00 10", "swi #0x10", "E1 02 00 91", "swp r0,r1,[r2]", "E1 42 00 91", "swpb r0,r1,[r2]",
"E1 30 00 01", "teq r0,r1", "E1 10 00 01", "tst r0,r1", "E0 A1 03 92", "umlal r0,r1,r2,r3",
"E0 81 03 92", "umull r0,r1,r2,r3", };
disassembleInstArray(insts, armOptions);
}
@Test
public void testArmVFPInstructions() {
System.out.println("\n====================== ARM VFP ======================\n");
String[] insts = { "EE B0 0B C1", "fabsd d0,d1", "EE B0 0A E0", "fabss s0,s1", "EE 31 0B 02", "faddd d0,d1,d2",
"EE 30 0A 81", "fadds s0,s1,s2", "EE B4 0B 41", "fcmpd d0,d1", "EE B4 0A 60", "fcmps s0,s1",
"EE B4 0B C1", "fcmped d0,d1", "EE B4 0A E0", "fcmpes s0,s1", "EE B5 0B C0", "fcmpezd d0",
"EE B5 0A C0", "fcmpezs s0", "EE B5 0B 40", "fcmpzd d0", "EE B5 0A 40", "fcmpzs s0", "EE B0 0B 41",
"fcpyd d0,d1", "EE B0 0A 60", "fcpys s0,s1", "EE B7 0A E0", "fcvtds d0,s1", "EE B7 0B C1",
"fcvtsd s0,d1", "EE 81 0B 02", "fdivd d0,d1,d2", "EE 80 0A 81", "fdivs s0,s1,s2", "ED 91 0B 01",
"fldd d0,[r1,#0x4]", "ED 91 0A 01", "flds s0,[r1,#0x4]", "EC 90 1B 06", "fldmiad r0,{d1,d2,d3}",
"EC D0 0A 03", "fldmias r0,{s1,s2,s3}", "EE 01 0B 02", "fmacd d0,d1,d2", "EE 00 0A 81",
"fmacs s0,s1,s2", "EE 20 1B 10", "fmdhr d0,r1", "EE 00 1B 10", "fmdlr d0,r1", "EC 42 1B 10",
"fmdrr d0,r1,r2", "EE 31 0B 10", "fmrdh r0,d1", "EE 11 0B 10", "fmrdl r0,d1", "EC 51 0B 12",
"fmrrd r0,r1,d2", "EC 51 0A 11", "fmrrs r0,r1,{s2,s3}", "EE 10 0A 90", "fmrs r0,s1", "0E F1 FA 10",
"fmstateq", "EE F1 0A 10", "fmrx r0,fpscr", "EE 11 0B 02", "fmscd d0,d1,d2", "EE 10 0A 81",
"fmscs s0,s1,s2", "EE 00 1A 10", "fmsr s0,r1", "EC 43 2A 10", "fmsrr {s0,s1},r2,r3", "EE 21 0B 02",
"fmuld d0,d1,d2", "EE 20 0A 81", "fmuls s0,s1,s2", "EE E0 1A 10", "fmxr fpsid,r1", "EE B1 0B 41",
"fnegd d0,d1", "EE B1 0A 60", "fnegs s0,s1", "EE 01 0B 42", "fnmacd d0,d1,d2", "EE 00 0A C1",
"fnmacs s0,s1,s2", "EE 11 0B 42", "fnmscd d0,d1,d2", "EE 10 0A C1", "fnmscs s0,s1,s2", "EE 21 0B 42",
"fnmuld d0,d1,d2", "EE 20 0A C1", "fnmuls s0,s1,s2", "EE B8 0B E0", "fsitod d0,s1", "EE B8 0A E0",
"fsitos s0,s1", "EE B1 0B C1", "fsqrtd d0,d1", "EE B1 0A E0", "fsqrts s0,s1", "ED 01 0B 01",
"fstd d0,[r1,#-0x4]", "ED 01 0A 01", "fsts s0,[r1,#-0x4]", "EC 80 1B 06", "fstmiad r0,{d1,d2,d3}",
"EC C0 0A 03", "fstmias r0,{s1,s2,s3}", "EE 31 0B 42", "fsubd d0,d1,d2", "EE 30 0A C1",
"fsubs s0,s1,s2", "EE BD 0B 41", "ftosid s0,d1", "EE BD 0A 60", "ftosis s0,s1", "EE BC 0B 41",
"ftouid s0,d1", "EE BC 0A 60", "ftouis s0,s1", "EE B8 0B 60", "fuitod d0,s1", "EE B8 0A 60",
"fuitos s0,s1", };
disassembleInstArray(insts, armOptions);
}
/**
* Test for ARM condition code.
*/
@Test
public void testArmConditionCode() {
System.out.println("\n================ ARM Condition Code ================\n");
String[] insts = { "00 A1 00 02", "adceq r0,r1,r2", "10 A1 00 02", "adcne r0,r1,r2", "20 A1 00 02",
"adccs r0,r1,r2", "30 A1 00 02", "adccc r0,r1,r2", "40 A1 00 02", "adcmi r0,r1,r2", "50 A1 00 02",
"adcpl r0,r1,r2", "60 A1 00 02", "adcvs r0,r1,r2", "70 A1 00 02", "adcvc r0,r1,r2", "80 A1 00 02",
"adchi r0,r1,r2", "90 A1 00 02", "adcls r0,r1,r2", "A0 A1 00 02", "adcge r0,r1,r2", "B0 A1 00 02",
"adclt r0,r1,r2", "C0 A1 00 02", "adcgt r0,r1,r2", "D0 A1 00 02", "adcle r0,r1,r2", "E0 A1 00 02",
"adc r0,r1,r2", };
disassembleInstArray(insts, armOptions);
}
/**
* Test for ARM addressing mode 1 (shifter operand).
*/
@Test
public void testArmAddrMode1() {
System.out.println("\n================== ARM Addr Mode 1 ==================\n");
String[] insts = { "E2 81 00 11", "add r0,r1,#0x11", "E0 81 00 02", "add r0,r1,r2", "E0 81 08 82",
"add r0,r1,r2,lsl #0x11", "E0 81 03 12", "add r0,r1,r2,lsl r3", "E0 81 08 A2",
"add r0,r1,r2,lsr #0x11", "E0 81 03 32", "add r0,r1,r2,lsr r3", "E0 81 08 C2",
"add r0,r1,r2,asr #0x11", "E0 81 03 52", "add r0,r1,r2,asr r3", "E0 81 08 E2",
"add r0,r1,r2,ror #0x11", "E0 81 03 72", "add r0,r1,r2,ror r3", "E0 81 00 62", "add r0,r1,r2,rrx", };
disassembleInstArray(insts, armOptions);
}
/**
* Test for ARM addressing mode 2.
*/
@Test
public void testArmAddrMode2() {
System.out.println("\n================== ARM Addr Mode 2 ==================\n");
String[] insts = { "E5 91 00 11", "ldr r0,[r1,#0x11]", "E5 11 00 11", "ldr r0,[r1,#-0x11]", "E7 91 00 02",
"ldr r0,[r1,r2]", "E7 11 00 02", "ldr r0,[r1,-r2]", "E7 91 08 82", "ldr r0,[r1,r2,lsl #0x11]",
"E7 91 08 A2", "ldr r0,[r1,r2,lsr #0x11]", "E7 91 08 C2", "ldr r0,[r1,r2,asr #0x11]", "E7 91 08 E2",
"ldr r0,[r1,r2,ror #0x11]", "E7 91 00 62", "ldr r0,[r1,r2,rrx]", "E7 11 08 82",
"ldr r0,[r1,-r2,lsl #0x11]", "E7 11 08 A2", "ldr r0,[r1,-r2,lsr #0x11]", "E7 11 08 C2",
"ldr r0,[r1,-r2,asr #0x11]", "E7 11 08 E2", "ldr r0,[r1,-r2,ror #0x11]", "E7 11 00 62",
"ldr r0,[r1,-r2,rrx]", "E5 B1 00 11", "ldr r0,[r1,#0x11]!", "E5 31 00 11", "ldr r0,[r1,#-0x11]!",
"E7 B1 00 02", "ldr r0,[r1,r2]!", "E7 31 00 02", "ldr r0,[r1,-r2]!", "E7 B1 08 82",
"ldr r0,[r1,r2,lsl #0x11]!", "E7 B1 08 A2", "ldr r0,[r1,r2,lsr #0x11]!", "E7 B1 08 C2",
"ldr r0,[r1,r2,asr #0x11]!", "E7 B1 08 E2", "ldr r0,[r1,r2,ror #0x11]!", "E7 B1 00 62",
"ldr r0,[r1,r2,rrx]!", "E7 31 08 82", "ldr r0,[r1,-r2,lsl #0x11]!", "E7 31 08 A2",
"ldr r0,[r1,-r2,lsr #0x11]!", "E7 31 08 C2", "ldr r0,[r1,-r2,asr #0x11]!", "E7 31 08 E2",
"ldr r0,[r1,-r2,ror #0x11]!", "E7 31 00 62", "ldr r0,[r1,-r2,rrx]!", "E4 91 00 11",
"ldr r0,[r1],#0x11", "E4 11 00 11", "ldr r0,[r1],#-0x11", "E6 91 00 02", "ldr r0,[r1],r2",
"E6 11 00 02", "ldr r0,[r1],-r2", "E6 91 08 82", "ldr r0,[r1],r2,lsl #0x11", "E6 91 08 A2",
"ldr r0,[r1],r2,lsr #0x11", "E6 91 08 C2", "ldr r0,[r1],r2,asr #0x11", "E6 91 08 E2",
"ldr r0,[r1],r2,ror #0x11", "E6 91 00 62", "ldr r0,[r1],r2,rrx", "E6 11 08 82",
"ldr r0,[r1],-r2,lsl #0x11", "E6 11 08 A2", "ldr r0,[r1],-r2,lsr #0x11", "E6 11 08 C2",
"ldr r0,[r1],-r2,asr #0x11", "E6 11 08 E2", "ldr r0,[r1],-r2,ror #0x11", "E6 11 00 62",
"ldr r0,[r1],-r2,rrx", };
disassembleInstArray(insts, armOptions);
}
/**
* Test for ARM addressing mode 3.
*/
@Test
public void testArmAddrMode3() {
System.out.println("\n================== ARM Addr Mode 3 ==================\n");
String[] insts = { "E1 C1 01 B0", "strh r0,[r1,#0x10]", "E1 41 01 B0", "strh r0,[r1,#-0x10]", "E1 81 00 B2",
"strh r0,[r1,r2]", "E1 01 00 B2", "strh r0,[r1,-r2]", "E1 E1 01 B0", "strh r0,[r1,#0x10]!",
"E1 61 01 B0", "strh r0,[r1,#-0x10]!", "E1 A1 00 B2", "strh r0,[r1,r2]!", "E1 21 00 B2",
"strh r0,[r1,-r2]!", "E0 C1 01 B0", "strh r0,[r1],#0x10", "E0 41 01 B0", "strh r0,[r1],#-0x10",
"E0 81 00 B2", "strh r0,[r1],r2", "E0 01 00 B2", "strh r0,[r1],-r2", };
disassembleInstArray(insts, armOptions);
}
/**
* Test for ARM addressing mode 4.
*/
@Test
public void testArmAddrMode4() {
System.out.println("\n================== ARM Addr Mode 4 ==================\n");
String[] insts = { "E8 90 00 06", "ldmia r0,{r1,r2}", "E9 90 00 06", "ldmib r0,{r1,r2}", "E8 10 00 06",
"ldmda r0,{r1,r2}", "E9 10 00 06", "ldmdb r0,{r1,r2}", };
disassembleInstArray(insts, armOptions);
}
/**
* Test for ARM addressing mode 5.
*/
@Test
public void testArmAddrMode5() {
System.out.println("\n================== ARM Addr Mode 5 ==================\n");
String[] insts = { "ED 92 10 04", "ldc p0,cr1,[r2,#0x10]", "ED 12 10 04", "ldc p0,cr1,[r2,#-0x10]",
"ED B2 10 04", "ldc p0,cr1,[r2,#0x10]!", "ED 32 10 04", "ldc p0,cr1,[r2,#-0x10]!", "EC B2 10 04",
"ldc p0,cr1,[r2],#0x10", "EC 32 10 04", "ldc p0,cr1,[r2],#-0x10", "EC 92 10 00", "ldc p0,cr1,[r2]", };
disassembleInstArray(insts, armOptions);
}
/**
* Test for ARM branching instructions.
*/
@Test
public void testArmBranches() {
armOptions.put(IDisassemblerOptions.MNEMONICS_SHOW_ADDRESS, true);
armOptions.put(IDisassemblerOptions.MNEMONICS_SHOW_BYTES, true);
System.out.println("\n=================== ARM Branches ====================\n");
disassembleInst(0x00000004, "ea ff ff fe", new JumpToAddress(0x00000004, false, false),
"4: ea ff ff fe b 0x0", armOptions);
disassembleInst(0x00000004, "eb ff ff fe", new JumpToAddress(0x00000004, false, true),
"4: eb ff ff fe bl 0x0", armOptions);
disassembleInst(0x00000004, "fa ff ff fe", new JumpToAddress(0x00000004, true, true),
"4: fa ff ff fe blx 0x0", armOptions);
disassembleInst(0x00000004, "e1 2f ff 30", new JumpToAddress("r0", false, true),
"4: e1 2f ff 30 blx r0", armOptions);
disassembleInst(0x00000004, "e1 2f ff 10", new JumpToAddress("r0", false, false),
"4: e1 2f ff 10 bx r0", armOptions);
disassembleInst(0x00000004, "e1 a0 f0 0e", new JumpToAddress("lr", false, false),
"4: e1 a0 f0 0e mov pc,lr", armOptions);
}
/**
* Test for Thumb instructions.
*/
@Test
public void testThumbInstructions() {
System.out.println("\n======================= Thumb =======================\n");
String[] insts = { "41 48", "adc r0,r1", "1D 08", "add r0,r1,#0x4", "30 04", "add r0,#0x4", "18 88",
"add r0,r1,r2", "44 48", "add r0,r9", "A0 01", "add r0,pc,#0x4", "A8 01", "add r0,sp,#0x4", "B0 01",
"add sp,#0x4", "40 08", "and r0,r1", "10 88", "asr r0,r1,#0x2", "41 08", "asr r0,r1", "D0 FE", "beq 0",
"E7 FE", "b 0", "43 88", "bic r0,r1", "BE 01", "bkpt #0x1", "F7 FF FF FE", "bl 0", "F7 FF EF FE",
"blx 0", "47 80", "blx r0", "47 00", "bx r0", "42 C8", "cmn r0,r1", "28 01", "cmp r0,#1", "42 88",
"cmp r0,r1", "45 48", "cmp r0,r9", "B6 67", "cpsie aif", "46 48", "cpy r0,r9", "40 48", "eor r0,r1",
"C8 0E", "ldmia r0!,{r1,r2,r3}", "68 48", "ldr r0,[r1,#0x4]", "58 88", "ldr r0,[r1,r2]", "48 01",
"ldr r0,[pc,#0x4]", "98 01", "ldr r0,[sp,#0x4]", "78 88", "ldrb r0,[r1,#0x2]", "5C 88",
"ldrb r0,[r1,r2]", "88 48", "ldrh r0,[r1,#0x2]", "5A 88", "ldrh r0,[r1,r2]", "56 88",
"ldrsb r0,[r1,r2]", "5E 88", "ldrsh r0,[r1,r2]", "00 88", "lsl r0,r1,#0x2", "40 88", "lsl r0,r1",
"08 88", "lsr r0,r1,#0x2", "40 C8", "lsr r0,r1", "20 01", "mov r0,#1", "1C 08", "mov r0,r1", "43 48",
"mul r0,r1", "43 C8", "mvn r0,r1", "42 48", "neg r0,r1", "43 08", "orr r0,r1", "BC 0E",
"pop {r1,r2,r3}", "B4 0E", "push {r1,r2,r3}", "BA 08", "rev r0,r1", "BA 48", "rev16 r0,r1", "BA C8",
"revsh r0,r1", "41 C8", "ror r0,r1", "41 88", "sbc r0,r1", "B6 58", "setend be", "C0 0E",
"stmia r0!,{r1,r2,r3}", "60 48", "str r0,[r1,#0x4]", "50 88", "str r0,[r1,r2]", "90 01",
"str r0,[sp,#0x4]", "70 88", "strb r0,[r1,#0x2]", "54 88", "strb r0,[r1,r2]", "80 48",
"strh r0,[r1,#0x2]", "52 88", "strh r0,[r1,r2]", "1F 08", "sub r0,r1,#0x4", "38 04", "sub r0,#0x4",
"1A 88", "sub r0,r1,r2", "B0 81", "sub sp,#0x4", "DF 00", "swi #0x0", "B2 48", "sxtb r0,r1", "B2 08",
"sxth r0,r1", "42 08", "tst r0,r1", "B2 C8", "uxtb r0,r1", "B2 88", "uxth r0,r1", };
disassembleInstArray(insts, thumbOptions);
}
/**
* Test for Thumb branching instructions.
*/
@Test
public void testThumbBranches() {
thumbOptions.put(IDisassemblerOptions.MNEMONICS_SHOW_ADDRESS, true);
thumbOptions.put(IDisassemblerOptions.MNEMONICS_SHOW_BYTES, true);
System.out.println("\n=================== Thumb Branches ==================\n");
disassembleInst(0x00000004, "d0 fe", new JumpToAddress(0x00000004, false, false),
"4: d0 fe beq 0x0", thumbOptions);
disassembleInst(0x00000004, "e7 fe", new JumpToAddress(0x00000004, true, false),
"4: e7 fe b 0x0", thumbOptions);
disassembleInst(0x00000004, "f7 ff ff fe", new JumpToAddress(0x00000004, true, true),
"4: f7 ff ff fe bl 0", thumbOptions);
disassembleInst(0x00000004, "f7 ff ef fe", new JumpToAddress(0x00000004, true, true),
"4: f7 ff ef fe blx 0", thumbOptions);
disassembleInst(0x00000004, "47 80", new JumpToAddress("r0", true, true),
"4: 47 80 blx r0", thumbOptions);
disassembleInst(0x00000004, "46 f7", new JumpToAddress("lr", true, false),
"4: 46 f7 cpy pc,lr", thumbOptions);
}
/**
* Convert hex string into byte array.
*/
private static byte[] getByteArray(String byteHexString) {
byteHexString = byteHexString.replaceAll("0x", "");
StringTokenizer tn = new StringTokenizer(byteHexString);
int cnt = tn.countTokens();
byte[] ret = new byte[cnt];
for (int i = 0; i < cnt; i++) {
ret[i] = (byte) Integer.parseInt(tn.nextToken(), 16);
}
return ret;
}
/**
* Disassemble a single instruction and verify the output.
*/
private void disassembleInst(long address, String code, IJumpToAddress expectedJumpAddr, String expectedMnemonics,
Map<String, Object> options) {
if (options == null)
options = armOptions;
IAddress addr = new Addr32(address);
ByteBuffer codeBuf = ByteBuffer.wrap(getByteArray(code));
String msg;
InstructionParserARM disa = new InstructionParserARM(addr, codeBuf);
IDisassembledInstruction output = null;
try {
output = disa.disassemble(options);
} catch (CoreException e) {
Assert.fail(e.getLocalizedMessage());
}
Assert.assertEquals(codeBuf.capacity(), output.getSize());
Assert.assertEquals(address, output.getAddress().getValue().longValue());
if (expectedJumpAddr != null) {
msg = "Address\n " + expectedJumpAddr + "\n not match expected\n " + output.getJumpToAddress();
Assert.assertNotNull(output.getJumpToAddress());
Assert.assertEquals(msg, expectedJumpAddr, output.getJumpToAddress());
}
if (expectedMnemonics != null) {
msg = "Mnemonics\n " + output.getMnemonics() + "\n not match expected\n " + expectedMnemonics;
Assert
.assertTrue(msg, TestUtils.stringCompare(expectedMnemonics, output.getMnemonics(), false, true,
true));
}
System.out.println(output.getMnemonics());
}
/**
* Disassemble an array of instructions and verify the output.
*/
private void disassembleInstArray(String[] insts, Map<String, Object> options) {
if (insts.length % 2 != 0)
throw new IllegalArgumentException();
// Don't show address nor bytes
options.put(IDisassemblerOptions.MNEMONICS_SHOW_ADDRESS, false);
options.put(IDisassemblerOptions.MNEMONICS_SHOW_BYTES, false);
int cnt = insts.length;
for (int i = 0; i < cnt; i += 2) {
disassembleInst(0 /* don't care */, insts[i], null /* don't care */, insts[i + 1], options);
}
}
}