@@ -260,8 +260,8 @@ def regdst_eq_pc(op_str):
260260 to_jump = cb_table .get (line .mnemonic )(read_reg_val (line .op_str .split (", " )[0 ]))
261261
262262 if to_jump :
263- if '#' in line .op_str :
264- ret_addr = _parse_int (line .op_str .split ('#' )[- 1 ])
263+ if "#" in line .op_str :
264+ ret_addr = _parse_int (line .op_str .split ("#" )[- 1 ])
265265 else :
266266 ret_addr = read_reg_val (line .op_str )
267267
@@ -301,55 +301,62 @@ def regdst_eq_pc(op_str):
301301
302302 ret_addr = next_addr
303303
304- return ret_addr
305-
306304 elif line .mnemonic in ("ldr" ,):
305+
307306 if regdst_eq_pc (line .op_str ):
308- _pc , _ , rn_offset = line .op_str .partition (", " )
307+ _ , _ , rn_offset = line .op_str .partition (", " )
308+ r , _ , imm = rn_offset .strip ("[]!" ).partition (", #" )
309309
310310 if "]" in rn_offset .split (", " )[1 ]: # pre-indexed immediate
311- _ , r , imm = line .op_str .replace ("[" , "" ).replace ("]" , "" ).replace ("!" , "" ).replace ("#" , "" ).split (", " )
312- ret_addr = ql .unpack32 (ql .mem .read (_parse_int (imm ) + read_reg_val (r ), 4 ))
311+ ret_addr = ql .unpack32 (ql .mem .read (_parse_int (imm ) + read_reg_val (r ), ARM_INST_SIZE ))
313312
314313 else : # post-indexed immediate
315314 # FIXME: weired behavior, immediate here does not apply
316- _ , r , imm = line .op_str .replace ("[" , "" ).replace ("]" , "" ).replace ("!" , "" ).replace ("#" , "" ).split (", " )
317- ret_addr = ql .unpack32 (ql .mem .read (read_reg_val (r ), 4 ))
315+ ret_addr = ql .unpack32 (ql .mem .read (read_reg_val (r ), ARM_INST_SIZE ))
318316
319317 elif line .mnemonic in ("addls" , "addne" , "add" ) and regdst_eq_pc (line .op_str ):
320318 V , C , Z , N = get_cpsr (ql .reg .cpsr )
319+ r0 , r1 , r2 , * imm = line .op_str .split (", " )
321320
322- if line .mnemonic == "addls" and (C == 0 or Z == 1 ):
323- r0 , r1 , r2 , imm = line .op_str .split (", " )
324- # program counter is awalys 8 bytes ahead , when it comes with pc need to add extra 8 bytes
325- ret_addr = 8 + read_reg_val (r1 ) + read_reg_val (r2 ) * 4
321+ # program counter is awalys 8 bytes ahead when it comes with pc, need to add extra 8 bytes
322+ extra = 8 if 'pc' in (r0 , r1 , r2 ) else 0
323+
324+ if imm :
325+ expr = imm [0 ].split ()
326+ # TODO: should support more bit shifting and rotating operation
327+ if expr [0 ] == "lsl" : # logical shift left
328+ n = _parse_int (expr [- 1 ].strip ("#" )) * 2
326329
327- elif line .mnemonic == "addne" and Z == 0 :
328- r0 , r1 , r2 , * rest = line .op_str .split (", " )
329- ret_addr = 8 + read_reg_val (r1 ) + (read_reg_val (r2 ) * 4 if rest else read_reg_val (r2 ))
330+ if line .mnemonic == "addls" and (C == 0 or Z == 1 ):
331+ ret_addr = extra + read_reg_val (r1 ) + read_reg_val (r2 ) * n
330332
331- elif line .mnemonic == "add" :
332- r0 , r1 , r2 = line .op_str .split (", " )
333- ret_addr = 8 + sum (map (read_reg_val , [r1 , r2 ]))
333+ elif line .mnemonic == "add" or (line .mnemonic == "addne" and Z == 0 ):
334+ ret_addr = extra + read_reg_val (r1 ) + (read_reg_val (r2 ) * n if imm else read_reg_val (r2 ))
334335
335336 elif line .mnemonic in ("tbh" , "tbb" ):
336337
337338 cur_addr += ARM_INST_SIZE
339+ r0 , r1 , * imm = line .op_str .strip ("[]" ).split (", " )
340+
341+ if imm :
342+ expr = imm [0 ].split ()
343+ if expr [0 ] == "lsl" : # logical shift left
344+ n = _parse_int (expr [- 1 ].strip ("#" )) * 2
338345
339346 if line .mnemonic == "tbh" :
340- r0 , r1 , _ = line . op_str . strip ( "[" ). strip ( "]" ). split ( ", " )
341- r1 = read_reg_val (r1 ) * 2
347+
348+ r1 = read_reg_val (r1 ) * n
342349
343350 elif line .mnemonic == "tbb" :
344- r0 , r1 = line . op_str . strip ( "[" ). strip ( "]" ). split ( ", " )
351+
345352 r1 = read_reg_val (r1 )
346353
347- to_add = int .from_bytes (ql .mem .read (cur_addr + r1 , 2 if line .mnemonic == "tbh" else 1 ), byteorder = "little" ) * 2
354+ to_add = int .from_bytes (ql .mem .read (cur_addr + r1 , 2 if line .mnemonic == "tbh" else 1 ), byteorder = "little" ) * n
348355 ret_addr = cur_addr + to_add
349356
350357 elif line .mnemonic .startswith ("pop" ) and "pc" in line .op_str :
351358
352- ret_addr = ql .stack_read (line .op_str .strip ("{" ). strip ( " }" ).split (", " ).index ("pc" ) * 4 )
359+ ret_addr = ql .stack_read (line .op_str .strip ("{}" ).split (", " ).index ("pc" ) * ARM_INST_SIZE )
353360 if not { # step to next instruction if cond does not meet
354361 "pop" : lambda * _ : True ,
355362 "pop.w" : lambda * _ : True ,
0 commit comments