From 7bf24c066b09db65422e581827b6201fbfead467 Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
Date: Thu, 3 Apr 2014 19:03:55 -0400
Subject: [PATCH] added thumb mode emulation

---
 src/core/core.vcxproj          |   1 +
 src/core/core.vcxproj.filters  |   3 +
 src/core/src/arm/armemu.cpp    |   6 +-
 src/core/src/arm/armsupp.cpp   |   2 +-
 src/core/src/arm/skyeye_defs.h |   1 +
 src/core/src/arm/thumbemu.cpp  | 513 +++++++++++++++++++++++++++++++++
 6 files changed, 522 insertions(+), 4 deletions(-)
 create mode 100644 src/core/src/arm/thumbemu.cpp

diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj
index d6382b6348..c97abd0691 100644
--- a/src/core/core.vcxproj
+++ b/src/core/core.vcxproj
@@ -145,6 +145,7 @@
     <ClCompile Include="src\arm\armvirt.cpp" />
     <ClCompile Include="src\arm\disassembler\arm_disasm.cpp" />
     <ClCompile Include="src\arm\mmu\arm1176jzf_s_mmu.cpp" />
+    <ClCompile Include="src\arm\thumbemu.cpp" />
     <ClCompile Include="src\core.cpp" />
     <ClCompile Include="src\core_timing.cpp" />
     <ClCompile Include="src\elf\elf_reader.cpp" />
diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters
index 9fb4d2892d..7521c7e70a 100644
--- a/src/core/core.vcxproj.filters
+++ b/src/core/core.vcxproj.filters
@@ -40,6 +40,9 @@
     <ClCompile Include="src\arm\mmu\arm1176jzf_s_mmu.cpp">
       <Filter>arm\mmu</Filter>
     </ClCompile>
+    <ClCompile Include="src\arm\thumbemu.cpp">
+      <Filter>arm</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <Filter Include="arm">
diff --git a/src/core/src/arm/armemu.cpp b/src/core/src/arm/armemu.cpp
index 0b14a6166a..5e3a9cfbf3 100644
--- a/src/core/src/arm/armemu.cpp
+++ b/src/core/src/arm/armemu.cpp
@@ -936,10 +936,10 @@ ARMul_Emulate26 (ARMul_State * state)
            pipelined PC value is used when executing Thumb code, and also for
            dealing with the BL instruction.  */
         if (TFLAG) {
-            ARMword new;
+            ARMword new_instr;
 
             /* Check if in Thumb mode.  */
-            switch (ARMul_ThumbDecode (state, pc, instr, &new)) {
+            switch (ARMul_ThumbDecode(state, pc, instr, &new_instr)) {
             case t_undefined:
                 /* This is a Thumb instruction.  */
                 ARMul_UndefInstr (state, instr);
@@ -952,7 +952,7 @@ ARMul_Emulate26 (ARMul_State * state)
             case t_decoded:
                 /* ARM instruction available.  */
                 //printf("t decode %04lx -> %08lx\n", instr & 0xffff, new);
-                instr = new;
+                instr = new_instr;
                 /* So continue instruction decoding.  */
                 break;
             default:
diff --git a/src/core/src/arm/armsupp.cpp b/src/core/src/arm/armsupp.cpp
index c2b8399c93..75d326f2bc 100644
--- a/src/core/src/arm/armsupp.cpp
+++ b/src/core/src/arm/armsupp.cpp
@@ -140,7 +140,7 @@ ARMul_SetCPSR (ARMul_State * state, ARMword value)
 
 void
 ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs)
-{
+{  
 	state->Cpsr = ARMul_GetCPSR (state);
 	//chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
 	if (state->Mode != USER26MODE && state->Mode != USER32MODE ) {
diff --git a/src/core/src/arm/skyeye_defs.h b/src/core/src/arm/skyeye_defs.h
index 9c92b5242d..6562e595a7 100644
--- a/src/core/src/arm/skyeye_defs.h
+++ b/src/core/src/arm/skyeye_defs.h
@@ -4,6 +4,7 @@
 #include "common.h"
 
 #define MODE32
+#define MODET
 
 typedef struct
 {
diff --git a/src/core/src/arm/thumbemu.cpp b/src/core/src/arm/thumbemu.cpp
new file mode 100644
index 0000000000..032d84b653
--- /dev/null
+++ b/src/core/src/arm/thumbemu.cpp
@@ -0,0 +1,513 @@
+/*  thumbemu.c -- Thumb instruction emulation.
+    Copyright (C) 1996, Cygnus Software Technologies Ltd.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* We can provide simple Thumb simulation by decoding the Thumb
+instruction into its corresponding ARM instruction, and using the
+existing ARM simulator.  */
+
+#include "skyeye_defs.h"
+
+#ifndef MODET			/* required for the Thumb instruction support */
+#if 1
+#error "MODET needs to be defined for the Thumb world to work"
+#else
+#define MODET (1)
+#endif
+#endif
+
+#include "armdefs.h"
+#include "armemu.h"
+#include "armos.h"
+
+
+/* Decode a 16bit Thumb instruction.  The instruction is in the low
+   16-bits of the tinstr field, with the following Thumb instruction
+   held in the high 16-bits.  Passing in two Thumb instructions allows
+   easier simulation of the special dual BL instruction.  */
+
+tdstate
+ARMul_ThumbDecode (
+     ARMul_State *state,
+     ARMword pc,
+     ARMword tinstr,
+     ARMword *ainstr)
+{
+	tdstate valid = t_decoded;	/* default assumes a valid instruction */
+	ARMword next_instr;
+
+	if (state->bigendSig) {
+		next_instr = tinstr & 0xFFFF;
+		tinstr >>= 16;
+	}
+	else {
+		next_instr = tinstr >> 16;
+		tinstr &= 0xFFFF;
+	}
+
+#if 1				/* debugging to catch non updates */
+	*ainstr = 0xDEADC0DE;
+#endif
+
+	switch ((tinstr & 0xF800) >> 11) {
+	case 0:		/* LSL */
+	case 1:		/* LSR */
+	case 2:		/* ASR */
+		/* Format 1 */
+		*ainstr = 0xE1B00000	/* base opcode */
+			| ((tinstr & 0x1800) >> (11 - 5))	/* shift type */
+			|((tinstr & 0x07C0) << (7 - 6))	/* imm5 */
+			|((tinstr & 0x0038) >> 3)	/* Rs */
+			|((tinstr & 0x0007) << 12);	/* Rd */
+		break;
+	case 3:		/* ADD/SUB */
+		/* Format 2 */
+		{
+			ARMword subset[4] = {
+				0xE0900000,	/* ADDS Rd,Rs,Rn    */
+				0xE0500000,	/* SUBS Rd,Rs,Rn    */
+				0xE2900000,	/* ADDS Rd,Rs,#imm3 */
+				0xE2500000	/* SUBS Rd,Rs,#imm3 */
+			};
+			/* It is quicker indexing into a table, than performing switch
+			   or conditionals: */
+			*ainstr = subset[(tinstr & 0x0600) >> 9]	/* base opcode */
+				|((tinstr & 0x01C0) >> 6)	/* Rn or imm3 */
+				|((tinstr & 0x0038) << (16 - 3))	/* Rs */
+				|((tinstr & 0x0007) << (12 - 0));	/* Rd */
+		}
+		break;
+	case 4:		/* MOV */
+	case 5:		/* CMP */
+	case 6:		/* ADD */
+	case 7:		/* SUB */
+		/* Format 3 */
+		{
+			ARMword subset[4] = {
+				0xE3B00000,	/* MOVS Rd,#imm8    */
+				0xE3500000,	/* CMP  Rd,#imm8    */
+				0xE2900000,	/* ADDS Rd,Rd,#imm8 */
+				0xE2500000,	/* SUBS Rd,Rd,#imm8 */
+			};
+			*ainstr = subset[(tinstr & 0x1800) >> 11]	/* base opcode */
+				|((tinstr & 0x00FF) >> 0)	/* imm8 */
+				|((tinstr & 0x0700) << (16 - 8))	/* Rn */
+				|((tinstr & 0x0700) << (12 - 8));	/* Rd */
+		}
+		break;
+	case 8:		/* Arithmetic and high register transfers */
+		/* TODO: Since the subsets for both Format 4 and Format 5
+		   instructions are made up of different ARM encodings, we could
+		   save the following conditional, and just have one large
+		   subset. */
+		if ((tinstr & (1 << 10)) == 0) {
+			/* Format 4 */
+            enum OpcodeType { t_norm, t_shift, t_neg, t_mul };
+			struct ThumbOpcode {
+				ARMword opcode;
+                OpcodeType otype;
+            };
+
+            ThumbOpcode subset[16] = {
+				{
+				0xE0100000, t_norm},	/* ANDS Rd,Rd,Rs     */
+				{
+				0xE0300000, t_norm},	/* EORS Rd,Rd,Rs     */
+				{
+				0xE1B00010, t_shift},	/* MOVS Rd,Rd,LSL Rs */
+				{
+				0xE1B00030, t_shift},	/* MOVS Rd,Rd,LSR Rs */
+				{
+				0xE1B00050, t_shift},	/* MOVS Rd,Rd,ASR Rs */
+				{
+				0xE0B00000, t_norm},	/* ADCS Rd,Rd,Rs     */
+				{
+				0xE0D00000, t_norm},	/* SBCS Rd,Rd,Rs     */
+				{
+				0xE1B00070, t_shift},	/* MOVS Rd,Rd,ROR Rs */
+				{
+				0xE1100000, t_norm},	/* TST  Rd,Rs        */
+				{
+				0xE2700000, t_neg},	/* RSBS Rd,Rs,#0     */
+				{
+				0xE1500000, t_norm},	/* CMP  Rd,Rs        */
+				{
+				0xE1700000, t_norm},	/* CMN  Rd,Rs        */
+				{
+				0xE1900000, t_norm},	/* ORRS Rd,Rd,Rs     */
+				{
+				0xE0100090, t_mul},	/* MULS Rd,Rd,Rs     */
+				{
+				0xE1D00000, t_norm},	/* BICS Rd,Rd,Rs     */
+				{
+				0xE1F00000, t_norm}	/* MVNS Rd,Rs        */
+			};
+			*ainstr = subset[(tinstr & 0x03C0) >> 6].opcode;	/* base */
+			switch (subset[(tinstr & 0x03C0) >> 6].otype) {
+			case t_norm:
+				*ainstr |= ((tinstr & 0x0007) << 16)	/* Rn */
+					|((tinstr & 0x0007) << 12)	/* Rd */
+					|((tinstr & 0x0038) >> 3);	/* Rs */
+				break;
+			case t_shift:
+				*ainstr |= ((tinstr & 0x0007) << 12)	/* Rd */
+					|((tinstr & 0x0007) >> 0)	/* Rm */
+					|((tinstr & 0x0038) << (8 - 3));	/* Rs */
+				break;
+			case t_neg:
+				*ainstr |= ((tinstr & 0x0007) << 12)	/* Rd */
+					|((tinstr & 0x0038) << (16 - 3));	/* Rn */
+				break;
+			case t_mul:
+				*ainstr |= ((tinstr & 0x0007) << 16)	/* Rd */
+					|((tinstr & 0x0007) << 8)	/* Rs */
+					|((tinstr & 0x0038) >> 3);	/* Rm */
+				break;
+			}
+		}
+		else {
+			/* Format 5 */
+			ARMword Rd = ((tinstr & 0x0007) >> 0);
+			ARMword Rs = ((tinstr & 0x0038) >> 3);
+			if (tinstr & (1 << 7))
+				Rd += 8;
+			if (tinstr & (1 << 6))
+				Rs += 8;
+			switch ((tinstr & 0x03C0) >> 6) {
+			case 0x1:	/* ADD Rd,Rd,Hs */
+			case 0x2:	/* ADD Hd,Hd,Rs */
+			case 0x3:	/* ADD Hd,Hd,Hs */
+				*ainstr = 0xE0800000	/* base */
+					| (Rd << 16)	/* Rn */
+					|(Rd << 12)	/* Rd */
+					|(Rs << 0);	/* Rm */
+				break;
+			case 0x5:	/* CMP Rd,Hs */
+			case 0x6:	/* CMP Hd,Rs */
+			case 0x7:	/* CMP Hd,Hs */
+				*ainstr = 0xE1500000	/* base */
+					| (Rd << 16)	/* Rn */
+					|(Rd << 12)	/* Rd */
+					|(Rs << 0);	/* Rm */
+				break;
+			case 0x9:	/* MOV Rd,Hs */
+			case 0xA:	/* MOV Hd,Rs */
+			case 0xB:	/* MOV Hd,Hs */
+				*ainstr = 0xE1A00000	/* base */
+					| (Rd << 16)	/* Rn */
+					|(Rd << 12)	/* Rd */
+					|(Rs << 0);	/* Rm */
+				break;
+			case 0xC:	/* BX Rs */
+			case 0xD:	/* BX Hs */
+				*ainstr = 0xE12FFF10	/* base */
+					| ((tinstr & 0x0078) >> 3);	/* Rd */
+				break;
+			case 0x0:	/* UNDEFINED */
+			case 0x4:	/* UNDEFINED */
+			case 0x8:	/* UNDEFINED */
+				valid = t_undefined;
+				break;
+			case 0xE:	/* BLX */
+			case 0xF:	/* BLX */
+				if (state->is_v5) {
+					*ainstr = 0xE1200030	/* base */
+						|(Rs << 0);	/* Rm */
+				} else {
+					valid = t_undefined;
+				}
+				break;
+			}
+		}
+		break;
+	case 9:		/* LDR Rd,[PC,#imm8] */
+		/* Format 6 */
+		*ainstr = 0xE59F0000	/* base */
+			| ((tinstr & 0x0700) << (12 - 8))	/* Rd */
+			|((tinstr & 0x00FF) << (2 - 0));	/* off8 */
+		break;
+	case 10:
+	case 11:
+		/* TODO: Format 7 and Format 8 perform the same ARM encoding, so
+		   the following could be merged into a single subset, saving on
+		   the following boolean: */
+		if ((tinstr & (1 << 9)) == 0) {
+			/* Format 7 */
+			ARMword subset[4] = {
+				0xE7800000,	/* STR  Rd,[Rb,Ro] */
+				0xE7C00000,	/* STRB Rd,[Rb,Ro] */
+				0xE7900000,	/* LDR  Rd,[Rb,Ro] */
+				0xE7D00000	/* LDRB Rd,[Rb,Ro] */
+			};
+			*ainstr = subset[(tinstr & 0x0C00) >> 10]	/* base */
+				|((tinstr & 0x0007) << (12 - 0))	/* Rd */
+				|((tinstr & 0x0038) << (16 - 3))	/* Rb */
+				|((tinstr & 0x01C0) >> 6);	/* Ro */
+		}
+		else {
+			/* Format 8 */
+			ARMword subset[4] = {
+				0xE18000B0,	/* STRH  Rd,[Rb,Ro] */
+				0xE19000D0,	/* LDRSB Rd,[Rb,Ro] */
+				0xE19000B0,	/* LDRH  Rd,[Rb,Ro] */
+				0xE19000F0	/* LDRSH Rd,[Rb,Ro] */
+			};
+			*ainstr = subset[(tinstr & 0x0C00) >> 10]	/* base */
+				|((tinstr & 0x0007) << (12 - 0))	/* Rd */
+				|((tinstr & 0x0038) << (16 - 3))	/* Rb */
+				|((tinstr & 0x01C0) >> 6);	/* Ro */
+		}
+		break;
+	case 12:		/* STR Rd,[Rb,#imm5] */
+	case 13:		/* LDR Rd,[Rb,#imm5] */
+	case 14:		/* STRB Rd,[Rb,#imm5] */
+	case 15:		/* LDRB Rd,[Rb,#imm5] */
+		/* Format 9 */
+		{
+			ARMword subset[4] = {
+				0xE5800000,	/* STR  Rd,[Rb,#imm5] */
+				0xE5900000,	/* LDR  Rd,[Rb,#imm5] */
+				0xE5C00000,	/* STRB Rd,[Rb,#imm5] */
+				0xE5D00000	/* LDRB Rd,[Rb,#imm5] */
+			};
+			/* The offset range defends on whether we are transferring a
+			   byte or word value: */
+			*ainstr = subset[(tinstr & 0x1800) >> 11]	/* base */
+				|((tinstr & 0x0007) << (12 - 0))	/* Rd */
+				|((tinstr & 0x0038) << (16 - 3))	/* Rb */
+				|((tinstr & 0x07C0) >> (6 - ((tinstr & (1 << 12)) ? 0 : 2)));	/* off5 */
+		}
+		break;
+	case 16:		/* STRH Rd,[Rb,#imm5] */
+	case 17:		/* LDRH Rd,[Rb,#imm5] */
+		/* Format 10 */
+		*ainstr = ((tinstr & (1 << 11))	/* base */
+			   ? 0xE1D000B0	/* LDRH */
+			   : 0xE1C000B0)	/* STRH */
+			|((tinstr & 0x0007) << (12 - 0))	/* Rd */
+			|((tinstr & 0x0038) << (16 - 3))	/* Rb */
+			|((tinstr & 0x01C0) >> (6 - 1))	/* off5, low nibble */
+			|((tinstr & 0x0600) >> (9 - 8));	/* off5, high nibble */
+		break;
+	case 18:		/* STR Rd,[SP,#imm8] */
+	case 19:		/* LDR Rd,[SP,#imm8] */
+		/* Format 11 */
+		*ainstr = ((tinstr & (1 << 11))	/* base */
+			   ? 0xE59D0000	/* LDR */
+			   : 0xE58D0000)	/* STR */
+			|((tinstr & 0x0700) << (12 - 8))	/* Rd */
+			|((tinstr & 0x00FF) << 2);	/* off8 */
+		break;
+	case 20:		/* ADD Rd,PC,#imm8 */
+	case 21:		/* ADD Rd,SP,#imm8 */
+		/* Format 12 */
+		if ((tinstr & (1 << 11)) == 0) {
+			/* NOTE: The PC value used here should by word aligned */
+			/* We encode shift-left-by-2 in the rotate immediate field,
+			   so no shift of off8 is needed.  */
+			*ainstr = 0xE28F0F00	/* base */
+				| ((tinstr & 0x0700) << (12 - 8))	/* Rd */
+				|(tinstr & 0x00FF);	/* off8 */
+		}
+		else {
+			/* We encode shift-left-by-2 in the rotate immediate field,
+			   so no shift of off8 is needed.  */
+			*ainstr = 0xE28D0F00	/* base */
+				| ((tinstr & 0x0700) << (12 - 8))	/* Rd */
+				|(tinstr & 0x00FF);	/* off8 */
+		}
+		break;
+	case 22:
+	case 23:
+		if ((tinstr & 0x0F00) == 0x0000) {
+			/* Format 13 */
+			/* NOTE: The instruction contains a shift left of 2
+			   equivalent (implemented as ROR #30): */
+			*ainstr = ((tinstr & (1 << 7))	/* base */
+				   ? 0xE24DDF00	/* SUB */
+				   : 0xE28DDF00)	/* ADD */
+				|(tinstr & 0x007F);	/* off7 */
+		}
+		else if ((tinstr & 0x0F00) == 0x0e00)
+			*ainstr = 0xEF000000 | SWI_Breakpoint;
+		else {
+			/* Format 14 */
+			ARMword subset[4] = {
+				0xE92D0000,	/* STMDB sp!,{rlist}    */
+				0xE92D4000,	/* STMDB sp!,{rlist,lr} */
+				0xE8BD0000,	/* LDMIA sp!,{rlist}    */
+				0xE8BD8000	/* LDMIA sp!,{rlist,pc} */
+			};
+			*ainstr = subset[((tinstr & (1 << 11)) >> 10) | ((tinstr & (1 << 8)) >> 8)]	/* base */
+				|(tinstr & 0x00FF);	/* mask8 */
+		}
+		break;
+	case 24:		/* STMIA */
+	case 25:		/* LDMIA */
+		/* Format 15 */
+		*ainstr = ((tinstr & (1 << 11))	/* base */
+			   ? 0xE8B00000	/* LDMIA */
+			   : 0xE8A00000)	/* STMIA */
+			|((tinstr & 0x0700) << (16 - 8))	/* Rb */
+			|(tinstr & 0x00FF);	/* mask8 */
+		break;
+	case 26:		/* Bcc */
+	case 27:		/* Bcc/SWI */
+		if ((tinstr & 0x0F00) == 0x0F00) {
+			if (tinstr == (ARMul_ABORTWORD & 0xffff) &&
+					state->AbortAddr == pc) {
+				*ainstr = ARMul_ABORTWORD;
+				break;
+			}
+			/* Format 17 : SWI */
+			*ainstr = 0xEF000000;
+			/* Breakpoint must be handled specially.  */
+			if ((tinstr & 0x00FF) == 0x18)
+				*ainstr |= ((tinstr & 0x00FF) << 16);
+			/* New breakpoint value.  See gdb/arm-tdep.c  */
+			else if ((tinstr & 0x00FF) == 0xFE)
+				*ainstr |= SWI_Breakpoint;
+			else
+				*ainstr |= (tinstr & 0x00FF);
+		}
+		else if ((tinstr & 0x0F00) != 0x0E00) {
+			/* Format 16 */
+			int doit = FALSE;
+			/* TODO: Since we are doing a switch here, we could just add
+			   the SWI and undefined instruction checks into this
+			   switch to same on a couple of conditionals: */
+			switch ((tinstr & 0x0F00) >> 8) {
+			case EQ:
+				doit = ZFLAG;
+				break;
+			case NE:
+				doit = !ZFLAG;
+				break;
+			case VS:
+				doit = VFLAG;
+				break;
+			case VC:
+				doit = !VFLAG;
+				break;
+			case MI:
+				doit = NFLAG;
+				break;
+			case PL:
+				doit = !NFLAG;
+				break;
+			case CS:
+				doit = CFLAG;
+				break;
+			case CC:
+				doit = !CFLAG;
+				break;
+			case HI:
+				doit = (CFLAG && !ZFLAG);
+				break;
+			case LS:
+				doit = (!CFLAG || ZFLAG);
+				break;
+			case GE:
+				doit = ((!NFLAG && !VFLAG)
+					|| (NFLAG && VFLAG));
+				break;
+			case LT:
+				doit = ((NFLAG && !VFLAG)
+					|| (!NFLAG && VFLAG));
+				break;
+			case GT:
+				doit = ((!NFLAG && !VFLAG && !ZFLAG)
+					|| (NFLAG && VFLAG && !ZFLAG));
+				break;
+			case LE:
+				doit = ((NFLAG && !VFLAG)
+					|| (!NFLAG && VFLAG)) || ZFLAG;
+				break;
+			}
+			if (doit) {
+				state->Reg[15] = (pc + 4
+						  + (((tinstr & 0x7F) << 1)
+						     | ((tinstr & (1 << 7)) ?
+							0xFFFFFF00 : 0)));
+				FLUSHPIPE;
+			}
+			valid = t_branch;
+		}
+		else		/* UNDEFINED : cc=1110(AL) uses different format */
+			valid = t_undefined;
+		break;
+	case 28:		/* B */
+		/* Format 18 */
+		state->Reg[15] = (pc + 4 + (((tinstr & 0x3FF) << 1)
+					    | ((tinstr & (1 << 10)) ?
+					       0xFFFFF800 : 0)));
+		FLUSHPIPE;
+		valid = t_branch;
+		break;
+	case 29:
+		if(tinstr & 0x1)
+			valid = t_undefined;
+		else{
+			/* BLX 1 for armv5t and above */
+			ARMword tmp = (pc + 2);
+			state->Reg[15] =
+				(state->Reg[14] + ((tinstr & 0x07FF) << 1)) & 0xFFFFFFFC;
+			state->Reg[14] = (tmp | 1);
+			CLEART;
+			DEBUG_LOG(ARM11, "In %s, After  BLX(1),LR=0x%x,PC=0x%x, offset=0x%x\n", __FUNCTION__, state->Reg[14], state->Reg[15], (tinstr &0x7FF) << 1);
+			valid = t_branch;
+			FLUSHPIPE;
+		}
+		break;
+	case 30:		/* BL instruction 1 */
+		/* Format 19 */
+		/* There is no single ARM instruction equivalent for this Thumb
+		   instruction. To keep the simulation simple (from the user
+		   perspective) we check if the following instruction is the
+		   second half of this BL, and if it is we simulate it
+		   immediately.  */
+		state->Reg[14] = state->Reg[15]
+			+ (((tinstr & 0x07FF) << 12)
+			   | ((tinstr & (1 << 10)) ? 0xFF800000 : 0));
+		valid = t_branch;	/* in-case we don't have the 2nd half */
+		//tinstr = next_instr;	/* move the instruction down */
+		//if (((tinstr & 0xF800) >> 11) != 31)
+		//	break;	/* exit, since not correct instruction */
+		/* else we fall through to process the second half of the BL */
+		//pc += 2;	/* point the pc at the 2nd half */
+		state->Reg[15] = pc + 2;
+		FLUSHPIPE;
+		break;
+	case 31:		/* BL instruction 2 */
+		/* Format 19 */
+		/* There is no single ARM instruction equivalent for this
+		   instruction. Also, it should only ever be matched with the
+		   fmt19 "BL instruction 1" instruction. However, we do allow
+		   the simulation of it on its own, with undefined results if
+		   r14 is not suitably initialised.  */
+		{
+			ARMword tmp = (pc + 2);
+			state->Reg[15] =
+				(state->Reg[14] + ((tinstr & 0x07FF) << 1));
+			state->Reg[14] = (tmp | 1);
+			valid = t_branch;
+			FLUSHPIPE;
+		}
+		break;
+	}
+
+	return valid;
+}