+ ctxt->asmline = -1;
+
+ return ctxt;
+}
+
+#define IS_BRANCH 1
+#define IS_CALL 2
+#define IS_RET 4
+#define IS_ADDR11 8
+#define IS_ADDR16 16
+#define IS_COND 32
+
+struct instruction {
+ unsigned char flags;
+ unsigned char len;
+};
+
+static struct instruction instructions[] = {
+ [0x28] = { .flags = 0, .len = 1 }, /* ADD A,Rn */
+ [0x29] = { .flags = 0, .len = 1 }, /* ADD A,Rn */
+ [0x2A] = { .flags = 0, .len = 1 }, /* ADD A,Rn */
+ [0x2B] = { .flags = 0, .len = 1 }, /* ADD A,Rn */
+ [0x2C] = { .flags = 0, .len = 1 }, /* ADD A,Rn */
+ [0x2D] = { .flags = 0, .len = 1 }, /* ADD A,Rn */
+ [0x2E] = { .flags = 0, .len = 1 }, /* ADD A,Rn */
+ [0x2F] = { .flags = 0, .len = 1 }, /* ADD A,Rn */
+ [0x25] = { .flags = 0, .len = 2 }, /* ADD A,direct */
+ [0x26] = { .flags = 0, .len = 1 }, /* ADD A,@Ri */
+ [0x27] = { .flags = 0, .len = 1 }, /* ADD A,@Ri */
+ [0x24] = { .flags = 0, .len = 2 }, /* ADD A,#data */
+
+ [0x38] = { .flags = 0, .len = 1 }, /* ADDC A,Rn */
+ [0x39] = { .flags = 0, .len = 1 }, /* ADDC A,Rn */
+ [0x3A] = { .flags = 0, .len = 1 }, /* ADDC A,Rn */
+ [0x3B] = { .flags = 0, .len = 1 }, /* ADDC A,Rn */
+ [0x3C] = { .flags = 0, .len = 1 }, /* ADDC A,Rn */
+ [0x3D] = { .flags = 0, .len = 1 }, /* ADDC A,Rn */
+ [0x3E] = { .flags = 0, .len = 1 }, /* ADDC A,Rn */
+ [0x3F] = { .flags = 0, .len = 1 }, /* ADDC A,Rn */
+ [0x35] = { .flags = 0, .len = 2 }, /* ADDC A,direct */
+ [0x36] = { .flags = 0, .len = 1 }, /* ADDC A,@Ri */
+ [0x37] = { .flags = 0, .len = 1 }, /* ADDC A,@Ri */
+ [0x34] = { .flags = 0, .len = 2 }, /* ADDC A,#data */
+
+ [0x98] = { .flags = 0, .len = 1 }, /* SUBB A,Rn */
+ [0x99] = { .flags = 0, .len = 1 }, /* SUBB A,Rn */
+ [0x9A] = { .flags = 0, .len = 1 }, /* SUBB A,Rn */
+ [0x9B] = { .flags = 0, .len = 1 }, /* SUBB A,Rn */
+ [0x9C] = { .flags = 0, .len = 1 }, /* SUBB A,Rn */
+ [0x9D] = { .flags = 0, .len = 1 }, /* SUBB A,Rn */
+ [0x9E] = { .flags = 0, .len = 1 }, /* SUBB A,Rn */
+ [0x9F] = { .flags = 0, .len = 1 }, /* SUBB A,Rn */
+ [0x95] = { .flags = 0, .len = 2 }, /* SUBB A,direct */
+ [0x96] = { .flags = 0, .len = 1 }, /* SUBB A,@Ri */
+ [0x97] = { .flags = 0, .len = 1 }, /* SUBB A,@Ri */
+ [0x94] = { .flags = 0, .len = 2 }, /* SUBB A,#data */
+
+ [0x08] = { .flags = 0, .len = 1 }, /* INC Rn */
+ [0x09] = { .flags = 0, .len = 1 }, /* INC Rn */
+ [0x0A] = { .flags = 0, .len = 1 }, /* INC Rn */
+ [0x0B] = { .flags = 0, .len = 1 }, /* INC Rn */
+ [0x0C] = { .flags = 0, .len = 1 }, /* INC Rn */
+ [0x0D] = { .flags = 0, .len = 1 }, /* INC Rn */
+ [0x0E] = { .flags = 0, .len = 1 }, /* INC Rn */
+ [0x0F] = { .flags = 0, .len = 1 }, /* INC Rn */
+ [0x05] = { .flags = 0, .len = 2 }, /* INC direct */
+ [0x06] = { .flags = 0, .len = 1 }, /* INC @Ri */
+ [0x07] = { .flags = 0, .len = 1 }, /* INC @Ri */
+ [0x04] = { .flags = 0, .len = 1 }, /* INC A */
+
+ [0xA3] = { .flags = 0, .len = 1 }, /* INC DPTR */
+
+ [0x18] = { .flags = 0, .len = 1 }, /* DEC Rn */
+ [0x19] = { .flags = 0, .len = 1 }, /* DEC Rn */
+ [0x1A] = { .flags = 0, .len = 1 }, /* DEC Rn */
+ [0x1B] = { .flags = 0, .len = 1 }, /* DEC Rn */
+ [0x1C] = { .flags = 0, .len = 1 }, /* DEC Rn */
+ [0x1D] = { .flags = 0, .len = 1 }, /* DEC Rn */
+ [0x1E] = { .flags = 0, .len = 1 }, /* DEC Rn */
+ [0x1F] = { .flags = 0, .len = 1 }, /* DEC Rn */
+ [0x15] = { .flags = 0, .len = 2 }, /* DEC direct */
+ [0x16] = { .flags = 0, .len = 1 }, /* DEC @Ri */
+ [0x17] = { .flags = 0, .len = 1 }, /* DEC @Ri */
+ [0x14] = { .flags = 0, .len = 1 }, /* DEC A */
+
+ [0xA4] = { .flags = 0, .len = 1 }, /* MUL AB */
+ [0x84] = { .flags = 0, .len = 1 }, /* DIV AB */
+
+ [0xD4] = { .flags = 0, .len = 1 }, /* DA A */
+
+ [0x58] = { .flags = 0, .len = 1 }, /* ANL A,Rn */
+ [0x59] = { .flags = 0, .len = 1 }, /* ANL A,Rn */
+ [0x5A] = { .flags = 0, .len = 1 }, /* ANL A,Rn */
+ [0x5B] = { .flags = 0, .len = 1 }, /* ANL A,Rn */
+ [0x5C] = { .flags = 0, .len = 1 }, /* ANL A,Rn */
+ [0x5D] = { .flags = 0, .len = 1 }, /* ANL A,Rn */
+ [0x5E] = { .flags = 0, .len = 1 }, /* ANL A,Rn */
+ [0x5F] = { .flags = 0, .len = 1 }, /* ANL A,Rn */
+ [0x55] = { .flags = 0, .len = 2 }, /* ANL A,direct */
+ [0x56] = { .flags = 0, .len = 1 }, /* ANL A,@Ri */
+ [0x57] = { .flags = 0, .len = 1 }, /* ANL A,@Ri */
+ [0x54] = { .flags = 0, .len = 2 }, /* ANL A,#data */
+ [0x52] = { .flags = 0, .len = 2 }, /* ANL direct,A */
+ [0x53] = { .flags = 0, .len = 3 }, /* ANL direct,#data */
+
+ [0x48] = { .flags = 0, .len = 1 }, /* ORL A,Rn */
+ [0x49] = { .flags = 0, .len = 1 }, /* ORL A,Rn */
+ [0x4A] = { .flags = 0, .len = 1 }, /* ORL A,Rn */
+ [0x4B] = { .flags = 0, .len = 1 }, /* ORL A,Rn */
+ [0x4C] = { .flags = 0, .len = 1 }, /* ORL A,Rn */
+ [0x4D] = { .flags = 0, .len = 1 }, /* ORL A,Rn */
+ [0x4E] = { .flags = 0, .len = 1 }, /* ORL A,Rn */
+ [0x4F] = { .flags = 0, .len = 1 }, /* ORL A,Rn */
+ [0x45] = { .flags = 0, .len = 2 }, /* ORL A,direct */
+ [0x46] = { .flags = 0, .len = 1 }, /* ORL A,@Ri */
+ [0x47] = { .flags = 0, .len = 1 }, /* ORL A,@Ri */
+ [0x44] = { .flags = 0, .len = 2 }, /* ORL A,#data */
+ [0x42] = { .flags = 0, .len = 2 }, /* ORL direct,A */
+ [0x43] = { .flags = 0, .len = 3 }, /* ORL direct,#data */
+
+ [0x68] = { .flags = 0, .len = 1 }, /* XRL A,Rn */
+ [0x69] = { .flags = 0, .len = 1 }, /* XRL A,Rn */
+ [0x6A] = { .flags = 0, .len = 1 }, /* XRL A,Rn */
+ [0x6B] = { .flags = 0, .len = 1 }, /* XRL A,Rn */
+ [0x6C] = { .flags = 0, .len = 1 }, /* XRL A,Rn */
+ [0x6D] = { .flags = 0, .len = 1 }, /* XRL A,Rn */
+ [0x6E] = { .flags = 0, .len = 1 }, /* XRL A,Rn */
+ [0x6F] = { .flags = 0, .len = 1 }, /* XRL A,Rn */
+ [0x65] = { .flags = 0, .len = 2 }, /* XRL A,direct */
+ [0x66] = { .flags = 0, .len = 1 }, /* XRL A,@Ri */
+ [0x67] = { .flags = 0, .len = 1 }, /* XRL A,@Ri */
+ [0x64] = { .flags = 0, .len = 2 }, /* XRL A,#data */
+ [0x62] = { .flags = 0, .len = 2 }, /* XRL direct,A */
+ [0x63] = { .flags = 0, .len = 3 }, /* XRL direct,#data */
+
+ [0xE4] = { .flags = 0, .len = 1 }, /* CLR A */
+ [0xF4] = { .flags = 0, .len = 1 }, /* CPL A */
+
+ [0x23] = { .flags = 0, .len = 1 }, /* RL A */
+ [0x33] = { .flags = 0, .len = 1 }, /* RLC A */
+ [0x03] = { .flags = 0, .len = 1 }, /* RR A */
+ [0x13] = { .flags = 0, .len = 1 }, /* RRC A */
+
+ [0xC4] = { .flags = 0, .len = 1 }, /* SWAP A */
+
+ [0xE8] = { .flags = 0, .len = 1 }, /* MOV A,Rn */
+ [0xE9] = { .flags = 0, .len = 1 }, /* MOV A,Rn */
+ [0xEA] = { .flags = 0, .len = 1 }, /* MOV A,Rn */
+ [0xEB] = { .flags = 0, .len = 1 }, /* MOV A,Rn */
+ [0xEC] = { .flags = 0, .len = 1 }, /* MOV A,Rn */
+ [0xED] = { .flags = 0, .len = 1 }, /* MOV A,Rn */
+ [0xEE] = { .flags = 0, .len = 1 }, /* MOV A,Rn */
+ [0xEF] = { .flags = 0, .len = 1 }, /* MOV A,Rn */
+ [0xE5] = { .flags = 0, .len = 2 }, /* MOV A,direct */
+ [0xE6] = { .flags = 0, .len = 1 }, /* MOV A,@Ri */
+ [0xE7] = { .flags = 0, .len = 1 }, /* MOV A,@Ri */
+ [0x74] = { .flags = 0, .len = 2 }, /* MOV A,#data */
+
+ [0xF8] = { .flags = 0, .len = 1 }, /* MOV Rn,A */
+ [0xF9] = { .flags = 0, .len = 1 }, /* MOV Rn,A */
+ [0xFA] = { .flags = 0, .len = 1 }, /* MOV Rn,A */
+ [0xFB] = { .flags = 0, .len = 1 }, /* MOV Rn,A */
+ [0xFC] = { .flags = 0, .len = 1 }, /* MOV Rn,A */
+ [0xFD] = { .flags = 0, .len = 1 }, /* MOV Rn,A */
+ [0xFE] = { .flags = 0, .len = 1 }, /* MOV Rn,A */
+ [0xFF] = { .flags = 0, .len = 1 }, /* MOV Rn,A */
+
+ [0xA8] = { .flags = 0, .len = 2 }, /* MOV Rn,direct */
+ [0xA9] = { .flags = 0, .len = 2 }, /* MOV Rn,direct */
+ [0xAA] = { .flags = 0, .len = 2 }, /* MOV Rn,direct */
+ [0xAB] = { .flags = 0, .len = 2 }, /* MOV Rn,direct */
+ [0xAC] = { .flags = 0, .len = 2 }, /* MOV Rn,direct */
+ [0xAD] = { .flags = 0, .len = 2 }, /* MOV Rn,direct */
+ [0xAE] = { .flags = 0, .len = 2 }, /* MOV Rn,direct */
+ [0xAF] = { .flags = 0, .len = 2 }, /* MOV Rn,direct */
+
+ [0x78] = { .flags = 0, .len = 2 }, /* MOV Rn,#data */
+ [0x79] = { .flags = 0, .len = 2 }, /* MOV Rn,#data */
+ [0x7A] = { .flags = 0, .len = 2 }, /* MOV Rn,#data */
+ [0x7B] = { .flags = 0, .len = 2 }, /* MOV Rn,#data */
+ [0x7C] = { .flags = 0, .len = 2 }, /* MOV Rn,#data */
+ [0x7D] = { .flags = 0, .len = 2 }, /* MOV Rn,#data */
+ [0x7E] = { .flags = 0, .len = 2 }, /* MOV Rn,#data */
+ [0x7F] = { .flags = 0, .len = 2 }, /* MOV Rn,#data */
+
+ [0xF5] = { .flags = 0, .len = 2 }, /* MOV direct,A */
+ [0x88] = { .flags = 0, .len = 2 }, /* MOV direct,Rn */
+ [0x89] = { .flags = 0, .len = 2 }, /* MOV direct,Rn */
+ [0x8A] = { .flags = 0, .len = 2 }, /* MOV direct,Rn */
+ [0x8B] = { .flags = 0, .len = 2 }, /* MOV direct,Rn */
+ [0x8C] = { .flags = 0, .len = 2 }, /* MOV direct,Rn */
+ [0x8D] = { .flags = 0, .len = 2 }, /* MOV direct,Rn */
+ [0x8E] = { .flags = 0, .len = 2 }, /* MOV direct,Rn */
+ [0x8F] = { .flags = 0, .len = 2 }, /* MOV direct,Rn */
+ [0x85] = { .flags = 0, .len = 3 }, /* MOV direct,direct */
+ [0x86] = { .flags = 0, .len = 2 }, /* MOV direct,@Ri */
+ [0x87] = { .flags = 0, .len = 2 }, /* MOV direct,@Ri */
+ [0x75] = { .flags = 0, .len = 3 }, /* MOV direct,#data */
+
+ [0xF6] = { .flags = 0, .len = 1 }, /* MOV @Ri,A */
+ [0xF7] = { .flags = 0, .len = 1 }, /* MOV @Ri,A */
+ [0xA6] = { .flags = 0, .len = 2 }, /* MOV @Ri,direct */
+ [0xA7] = { .flags = 0, .len = 2 }, /* MOV @Ri,direct */
+ [0x76] = { .flags = 0, .len = 2 }, /* MOV @Ri,#data */
+ [0x77] = { .flags = 0, .len = 2 }, /* MOV @Ri,#data */
+
+
+ [0x90] = { .flags = 0, .len = 3 }, /* MOV DPTR,#data16 */
+
+ [0x93] = { .flags = 0, .len = 1 }, /* MOVC A,@A+DPTR */
+ [0x83] = { .flags = 0, .len = 1 }, /* MOVC A,@A+PC */
+
+ [0xE2] = { .flags = 0, .len = 1 }, /* MOVX A,@Ri */
+ [0xE3] = { .flags = 0, .len = 1 }, /* MOVX A,@Ri */
+ [0xE0] = { .flags = 0, .len = 1 }, /* MOVX A,@DPTR */
+ [0xF2] = { .flags = 0, .len = 1 }, /* MOVX @Ri,A */
+ [0xF3] = { .flags = 0, .len = 1 }, /* MOVX @Ri,A */
+ [0xF0] = { .flags = 0, .len = 1 }, /* MOVX @DPTR,A */
+
+ [0xC0] = { .flags = 0, .len = 2 }, /* PUSH direct */
+ [0xD0] = { .flags = 0, .len = 2 }, /* POP direct */
+ [0xF5] = { .flags = 0, .len = 2 }, /* MOV direct,A */
+ [0xF5] = { .flags = 0, .len = 2 }, /* MOV direct,A */
+ [0xF5] = { .flags = 0, .len = 2 }, /* MOV direct,A */
+ [0xF5] = { .flags = 0, .len = 2 }, /* MOV direct,A */
+
+ [0xC8] = { .flags = 0, .len = 1 }, /* XCH A,Rn */
+ [0xC9] = { .flags = 0, .len = 1 }, /* XCH A,Rn */
+ [0xCA] = { .flags = 0, .len = 1 }, /* XCH A,Rn */
+ [0xCB] = { .flags = 0, .len = 1 }, /* XCH A,Rn */
+ [0xCC] = { .flags = 0, .len = 1 }, /* XCH A,Rn */
+ [0xCD] = { .flags = 0, .len = 1 }, /* XCH A,Rn */
+ [0xCE] = { .flags = 0, .len = 1 }, /* XCH A,Rn */
+ [0xCF] = { .flags = 0, .len = 1 }, /* XCH A,Rn */
+ [0xC5] = { .flags = 0, .len = 2 }, /* XCH A,direct */
+ [0xC6] = { .flags = 0, .len = 1 }, /* XCH A,@Ri */
+ [0xC7] = { .flags = 0, .len = 1 }, /* XCH A,@Ri */
+ [0xD6] = { .flags = 0, .len = 1 }, /* XCHD A,@Ri */
+ [0xD7] = { .flags = 0, .len = 1 }, /* XCHD A,@Ri */
+
+ [0x11] = { .flags = IS_CALL, .len = 2 }, /* ACALL addr11 */
+ [0x31] = { .flags = IS_CALL, .len = 2 }, /* ACALL addr11 */
+ [0x51] = { .flags = IS_CALL, .len = 2 }, /* ACALL addr11 */
+ [0x71] = { .flags = IS_CALL, .len = 2 }, /* ACALL addr11 */
+ [0x91] = { .flags = IS_CALL, .len = 2 }, /* ACALL addr11 */
+ [0xb1] = { .flags = IS_CALL, .len = 2 }, /* ACALL addr11 */
+ [0xd1] = { .flags = IS_CALL, .len = 2 }, /* ACALL addr11 */
+ [0xf1] = { .flags = IS_CALL, .len = 2 }, /* ACALL addr11 */
+ [0x12] = { .flags = IS_CALL, .len = 3 }, /* LCALL addr16 */
+
+ [0x22] = { .flags = IS_RET, .len = 1 }, /* RET */
+ [0x32] = { .flags = IS_RET, .len = 1 }, /* RETI */
+
+ [0x01] = { .flags = IS_BRANCH, .len = 2 }, /* AJMP addr11 */
+ [0x21] = { .flags = IS_BRANCH, .len = 2 }, /* AJMP addr11 */
+ [0x41] = { .flags = IS_BRANCH, .len = 2 }, /* AJMP addr11 */
+ [0x61] = { .flags = IS_BRANCH, .len = 2 }, /* AJMP addr11 */
+ [0x81] = { .flags = IS_BRANCH, .len = 2 }, /* AJMP addr11 */
+ [0xa1] = { .flags = IS_BRANCH, .len = 2 }, /* AJMP addr11 */
+ [0xc1] = { .flags = IS_BRANCH, .len = 2 }, /* AJMP addr11 */
+ [0xe1] = { .flags = IS_BRANCH, .len = 2 }, /* AJMP addr11 */
+ [0x02] = { .flags = IS_BRANCH, .len = 3 }, /* LJMP addr16 */
+
+ [0x80] = { .flags = IS_BRANCH, .len = 2 }, /* SJMP rel */
+
+ [0x73] = { .flags = IS_BRANCH, .len = 1 }, /* JMP @A+DPTR */
+
+ [0x60] = { .flags = IS_BRANCH, .len = 2 }, /* JZ rel */
+ [0x70] = { .flags = IS_BRANCH, .len = 2 }, /* JNZ rel */
+ [0x40] = { .flags = IS_BRANCH, .len = 2 }, /* JC rel */
+ [0x50] = { .flags = IS_BRANCH, .len = 2 }, /* JNC rel */
+ [0x20] = { .flags = IS_BRANCH, .len = 3 }, /* JB bit,rel */
+ [0x30] = { .flags = IS_BRANCH, .len = 3 }, /* JNB bit,rel */
+ [0x10] = { .flags = IS_BRANCH, .len = 3 }, /* JBC bit,direct rel */
+
+ [0xB5] = { .flags = IS_BRANCH, .len = 3 }, /* CJNE A,direct rel */
+ [0xB4] = { .flags = IS_BRANCH, .len = 3 }, /* CJNE A,#data rel */
+ [0xB8] = { .flags = IS_BRANCH, .len = 3 }, /* CJNE Rn,#data rel */
+ [0xB9] = { .flags = IS_BRANCH, .len = 3 }, /* CJNE Rn,#data rel */
+ [0xBA] = { .flags = IS_BRANCH, .len = 3 }, /* CJNE Rn,#data rel */
+ [0xBB] = { .flags = IS_BRANCH, .len = 3 }, /* CJNE Rn,#data rel */
+ [0xBC] = { .flags = IS_BRANCH, .len = 3 }, /* CJNE Rn,#data rel */
+ [0xBD] = { .flags = IS_BRANCH, .len = 3 }, /* CJNE Rn,#data rel */
+ [0xBE] = { .flags = IS_BRANCH, .len = 3 }, /* CJNE Rn,#data rel */
+ [0xBF] = { .flags = IS_BRANCH, .len = 3 }, /* CJNE Rn,#data rel */
+ [0xB6] = { .flags = IS_BRANCH, .len = 3 }, /* CJNE @Ri,direct rel */
+ [0xB7] = { .flags = IS_BRANCH, .len = 3 }, /* CJNE @Ri,direct rel */
+
+ [0xD8] = { .flags = IS_BRANCH, .len = 2 }, /* DNJZ Rn,rel */
+ [0xD9] = { .flags = IS_BRANCH, .len = 2 }, /* DNJZ Rn,rel */
+ [0xDA] = { .flags = IS_BRANCH, .len = 2 }, /* DNJZ Rn,rel */
+ [0xDB] = { .flags = IS_BRANCH, .len = 2 }, /* DNJZ Rn,rel */
+ [0xDC] = { .flags = IS_BRANCH, .len = 2 }, /* DNJZ Rn,rel */
+ [0xDD] = { .flags = IS_BRANCH, .len = 2 }, /* DNJZ Rn,rel */
+ [0xDE] = { .flags = IS_BRANCH, .len = 2 }, /* DNJZ Rn,rel */
+ [0xDF] = { .flags = IS_BRANCH, .len = 2 }, /* DNJZ Rn,rel */
+ [0xD5] = { .flags = IS_BRANCH, .len = 3 }, /* DNJZ direct,rel */
+
+ [0x00] = { .flags = 0, .len = 1 }, /* NOP */
+
+ [0xC3] = { .flags = 0, .len = 1 }, /* CLR C */
+ [0xC2] = { .flags = 0, .len = 2 }, /* CLR bit */
+ [0xD3] = { .flags = 0, .len = 1 }, /* SETB C */
+ [0xD2] = { .flags = 0, .len = 2 }, /* SETB bit */
+
+ [0xB3] = { .flags = 0, .len = 1 }, /* CPL C */
+ [0xB2] = { .flags = 0, .len = 2 }, /* CPL bit */
+
+ [0x82] = { .flags = 0, .len = 2 }, /* ANL C,bit */
+ [0xB0] = { .flags = 0, .len = 2 }, /* ANL C,/bit */
+ [0x72] = { .flags = 0, .len = 2 }, /* ORL C,bit */
+ [0xA0] = { .flags = 0, .len = 2 }, /* ORL C,/bit */
+
+ [0xA2] = { .flags = 0, .len = 2 }, /* MOV C,bit */
+ [0x92] = { .flags = 0, .len = 2 }, /* MOV bit,C */
+
+ [0xA5] = { .flags = 0, .len = 1 }, /* TRAP */
+};
+
+#define RET 0x22
+#define RETI 0x32
+
+#define PUSH 0xC0
+#define POP 0xD0
+#define MOV_direct_A 0xF5
+#define MOV_A_direct 0xE5
+#define ADD_A_imm 0x24
+#define SP 0x81
+#define RET 0x22
+#define RETI 0x32
+#define LJMP_addr16 0x02
+#define SJMP_rel 0x80
+
+static int stack_change(unsigned addr)
+{
+ unsigned char insn;
+ unsigned char direct;
+
+ insn = simGetValue(addr, 'C', 1);
+ switch (insn) {
+ case PUSH:
+ return 1;
+ case POP:
+ return -1;
+ case MOV_direct_A:
+ direct = simGetValue(addr+1, 'C', 1);
+ if (direct == SP) {
+ unsigned char add_insn;
+ unsigned char add_direct;
+
+ add_insn = simGetValue(addr-2, 'C', 1);
+ if (add_insn == ADD_A_imm) {
+ add_direct = simGetValue(addr-1, 'C', 1);
+ return (signed char) add_direct;
+ }
+ }
+ break;
+ case RET:
+ return 0;
+ case RETI:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static int pc_change(unsigned addr, unsigned addrs[2])
+{
+ unsigned char insn;
+ unsigned new_addr;
+ signed char delta;
+ int len;
+
+ insn = simGetValue(addr, 'C', 1);
+ if (instructions[insn].flags & IS_RET)
+ return 0;
+
+ if (!(instructions[insn].flags & IS_BRANCH)) {
+ addrs[0] = addr + instructions[insn].len;
+ return 1;
+ }
+
+ if (insn == LJMP_addr16) {
+ addrs[0] = ((simGetValue(addr+1, 'C', 1) << 8) |
+ (simGetValue(addr+2, 'C', 1)));
+ return 1;
+ }
+
+ /* AJMP */
+ if ((insn & 0x1f) == 0x01) {
+ unsigned char direct = simGetValue(addr+1,'C', 1);
+
+ addrs[0] = ((addr + 2) & 0xf800) | ((insn & 0xe0) << 3) | direct;
+ return 1;
+ }
+
+ /* otherwise, relative branch */
+ len = instructions[insn].len;
+
+ delta = (signed char) simGetValue(addr+len-1, 'C', 1);
+ new_addr = (addr + len) + delta;
+
+ if (insn == SJMP_rel) {
+ addrs[0] = new_addr;
+ return 1;
+ }