Skip to content

Commit 93875f3

Browse files
committed
CHB:ARM: add predicate assignment instruction
1 parent af3ec25 commit 93875f3

File tree

8 files changed

+219
-28
lines changed

8 files changed

+219
-28
lines changed

CodeHawk/CHB/bchlibarm32/bCHARMDisassemblyUtils.ml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,28 @@ let get_it_condition_list (firstcond:int) (mask:int) =
139139
thencc::xyz
140140

141141

142+
let get_inverse_cc (cc: arm_opcode_cc_t): arm_opcode_cc_t option =
143+
match cc with
144+
| ACCEqual -> Some ACCNotEqual
145+
| ACCNotEqual -> Some ACCEqual
146+
| ACCCarrySet -> Some ACCCarryClear
147+
| ACCCarryClear -> Some ACCCarrySet
148+
| ACCNegative -> Some ACCNonNegative
149+
| ACCNonNegative -> Some ACCNegative
150+
| ACCOverflow -> Some ACCNoOverflow
151+
| ACCNoOverflow -> Some ACCOverflow
152+
| ACCUnsignedHigher -> Some ACCNotUnsignedHigher
153+
| ACCNotUnsignedHigher -> Some ACCUnsignedHigher
154+
| ACCSignedGE -> Some ACCSignedLT
155+
| ACCSignedLT -> Some ACCSignedGE
156+
| ACCSignedGT -> Some ACCSignedLE
157+
| ACCSignedLE -> Some ACCSignedGT
158+
| _ -> None
159+
160+
161+
let has_inverse_cc (cc: arm_opcode_cc_t): bool = Option.is_some (get_inverse_cc cc)
162+
163+
142164
let get_string_reference (floc:floc_int) (xpr:xpr_t) =
143165
try
144166
match xpr with

CodeHawk/CHB/bchlibarm32/bCHARMDisassemblyUtils.mli

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,8 @@ val get_interrupt_flags: int -> interrupt_flags_t
3939

4040
val get_it_condition_list: int -> int -> (string * arm_opcode_cc_t) list
4141

42+
val get_inverse_cc: arm_opcode_cc_t -> arm_opcode_cc_t option
43+
44+
val has_inverse_cc: arm_opcode_cc_t -> bool
45+
4246
val get_string_reference: floc_int -> xpr_t -> string option

CodeHawk/CHB/bchlibarm32/bCHARMInstructionAggregate.ml

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
============================================================================= *)
2727

2828
(* chlib *)
29+
open CHNumerical
2930
open CHPretty
3031

3132
(* chutil *)
@@ -39,6 +40,7 @@ open BCHLibTypes
3940
(* bchlibarm32 *)
4041
open BCHARMAssemblyInstruction
4142
open BCHARMAssemblyInstructions
43+
open BCHARMDisassemblyUtils
4244
open BCHARMJumptable
4345
open BCHARMTypes
4446
open BCHDisassembleARMInstruction
@@ -61,6 +63,9 @@ let arm_aggregate_kind_to_string (k: arm_aggregate_kind_t) =
6163
| LDMSTMSequence s -> s#toString
6264
| PseudoLDRSB (i1, _, _) -> "Pseudo LDRSB at " ^ i1#get_address#to_hex_string
6365
| PseudoLDRSH (i1, _, _) -> "Pseudo LDRSH at " ^ i1#get_address#to_hex_string
66+
| ARMPredicateAssignment (inverse, op) ->
67+
let inv = if inverse then " (inverse)" else "" in
68+
"predicate assignment to " ^ op#toString ^ inv
6469
| BXCall (_, i2) -> "BXCall at " ^ i2#get_address#to_hex_string
6570

6671

@@ -130,6 +135,11 @@ object (self)
130135
| PseudoLDRSH _ -> true
131136
| _ -> false
132137

138+
method is_predicate_assign =
139+
match self#kind with
140+
| ARMPredicateAssignment _ -> true
141+
| _ -> false
142+
133143
method write_xml (_node: xml_element_int) = ()
134144

135145
method toCHIF (_faddr: doubleword_int) = []
@@ -232,6 +242,20 @@ let make_pseudo_ldrsb_aggregate
232242
~anchor:asrinstr
233243

234244

245+
let make_predassign_aggregate
246+
(inverse: bool)
247+
(mov1: arm_assembly_instruction_int)
248+
(mov2: arm_assembly_instruction_int)
249+
(dstop: arm_operand_int): arm_instruction_aggregate_int =
250+
let kind = ARMPredicateAssignment (inverse, dstop) in
251+
make_arm_instruction_aggregate
252+
~kind
253+
~instrs:[mov1; mov2]
254+
~entry:mov1
255+
~exitinstr:mov2
256+
~anchor:mov2
257+
258+
235259
let disassemble_arm_instructions
236260
(ch: pushback_stream_int) (iaddr: doubleword_int) (n: int) =
237261
for _i = 1 to n do
@@ -393,7 +417,7 @@ let identify_pseudo_ldrsh
393417
ASR Rx, Rx, #0x18
394418
*)
395419
let identify_pseudo_ldrsb
396-
(ch: pushback_stream_int)
420+
(_ch: pushback_stream_int)
397421
(instr: arm_assembly_instruction_int):
398422
(arm_assembly_instruction_int
399423
* arm_assembly_instruction_int
@@ -422,13 +446,51 @@ let identify_pseudo_ldrsb
422446
when rd2#get_register = rd#get_register -> true
423447
| _ -> false)
424448
then
425-
Some (TR.tget_ok ldrbinstr_r, TR.tget_ok lslinstr_r, instr)
449+
Some (ldrbinstr, lslinstr, instr)
426450
else
427451
None
428452
| _ -> None)
429453
| _ -> None
430454

431455

456+
(* format of predicate assignment (in ARM): assigns the result of a test as a
457+
0/1 value to a register
458+
459+
MOVNE Rx, #0
460+
MOVEQ Rx, #1
461+
*)
462+
let identify_predicate_assignment
463+
(_ch: pushback_stream_int)
464+
(instr: arm_assembly_instruction_int):
465+
(bool
466+
* arm_assembly_instruction_int
467+
* arm_assembly_instruction_int
468+
* arm_operand_int) option =
469+
let is_zero imm = imm#to_numerical#equal numerical_zero in
470+
let is_one imm = imm#to_numerical#equal numerical_one in
471+
let is_zero_or_one imm = (is_zero imm) || (is_one imm) in
472+
match instr#get_opcode with
473+
| Move (false, c2, rd, imm2, _, _)
474+
when imm2#is_immediate && (is_zero_or_one imm2) && (has_inverse_cc c2) ->
475+
let rdreg = rd#get_register in
476+
let addr = instr#get_address in
477+
let movinstr_r = get_arm_assembly_instruction (addr#add_int (-4)) in
478+
(match TR.to_option movinstr_r with
479+
| Some movinstr ->
480+
(match movinstr#get_opcode with
481+
| Move (false, c1, rd, imm1, _, _)
482+
when imm1#is_immediate
483+
&& (is_zero_or_one imm1)
484+
&& (rd#get_register = rdreg)
485+
&& (not (imm1#to_numerical#equal imm2#to_numerical))
486+
&& (has_inverse_cc c1)
487+
&& ((Option.get (get_inverse_cc c1)) = c2) ->
488+
let inverse = is_zero imm2 in
489+
Some (inverse, movinstr, instr, rd)
490+
| _ -> None)
491+
| _ -> None)
492+
| _ -> None
493+
432494

433495
let identify_arm_aggregate
434496
(ch: pushback_stream_int)
@@ -486,4 +548,12 @@ let identify_arm_aggregate
486548
| Some (ldrbinstr, lslinstr, asrinstr) ->
487549
Some (make_pseudo_ldrsb_aggregate ldrbinstr lslinstr asrinstr)
488550
| _ -> None in
551+
let result =
552+
match result with
553+
| Some _ -> result
554+
| _ ->
555+
match identify_predicate_assignment ch instr with
556+
| Some (inverse, mov1, mov2, dstop) ->
557+
Some (make_predassign_aggregate inverse mov1 mov2 dstop)
558+
| _ -> None in
489559
result

CodeHawk/CHB/bchlibarm32/bCHARMOperand.ml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ open Xsimplify
4444
open BCHBasicTypes
4545
open BCHBCTypes
4646
open BCHBCTypeUtil
47-
open BCHConstantDefinitions
4847
open BCHCPURegisters
4948
open BCHDoubleword
5049
open BCHImmediate
@@ -64,6 +63,8 @@ module TR = CHTraceResult
6463
let x2p = xpr_formatter#pr_expr
6564
let p2s = pretty_to_string
6665

66+
let memmap = BCHGlobalMemoryMap.global_memory_map
67+
6768

6869
let log_error (tag: string) (msg: string): tracelogspec_t =
6970
mk_tracelog_spec ~tag:("arm_operand:" ^ tag) msg
@@ -617,8 +618,8 @@ object (self:'a)
617618
let imm = if unsigned then imm#to_unsigned else imm in
618619
(match imm#to_doubleword with
619620
| Some dw ->
620-
if has_symbolic_address_name dw then
621-
let name = get_symbolic_address_name dw in
621+
if memmap#has_location dw then
622+
let name = memmap#get_location_name dw in
622623
let var =
623624
floc#f#env#mk_global_memory_address
624625
~optname:(Some name) imm#to_numerical in
@@ -637,11 +638,11 @@ object (self:'a)
637638
| ARMAbsolute a when elf_header#is_program_address a ->
638639
num_constant_expr a#to_numerical
639640
| ARMLiteralAddress a ->
640-
if elf_header#is_program_address a then
641+
if elf_header#is_readonly_address a then
641642
let dw = elf_header#get_program_value a in
642-
if has_symbolic_address_name dw then
643-
let name = get_symbolic_address_name dw in
644-
let ty = get_symbolic_address_type_by_name name in
643+
if memmap#has_location dw then
644+
let name = memmap#get_location_name dw in
645+
let ty = memmap#get_location_type dw in
645646
if is_struct_type ty || is_array_type ty then
646647
let var =
647648
floc#f#env#mk_global_memory_address

CodeHawk/CHB/bchlibarm32/bCHARMTypes.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,6 +1531,7 @@ type arm_aggregate_kind_t =
15311531
arm_assembly_instruction_int
15321532
* arm_assembly_instruction_int
15331533
* arm_assembly_instruction_int
1534+
| ARMPredicateAssignment of bool * arm_operand_int
15341535
| BXCall of arm_assembly_instruction_int * arm_assembly_instruction_int
15351536

15361537

@@ -1556,6 +1557,7 @@ class type arm_instruction_aggregate_int =
15561557
method is_bx_call: bool
15571558
method is_pseudo_ldrsh: bool
15581559
method is_pseudo_ldrsb: bool
1560+
method is_predicate_assign: bool
15591561

15601562
(* i/o *)
15611563
method write_xml: xml_element_int -> unit

CodeHawk/CHB/bchlibarm32/bCHFnARMDictionary.ml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,6 +1546,56 @@ object (self)
15461546
let (tags, args) = add_optional_instr_condition tagstring args c in
15471547
(tags, args)
15481548

1549+
| Move _ when instr#is_aggregate_anchor ->
1550+
let finfo = floc#f in
1551+
let ctxtiaddr = floc#l#ci in
1552+
if finfo#has_associated_cc_setter ctxtiaddr then
1553+
let testiaddr = finfo#get_associated_cc_setter ctxtiaddr in
1554+
let testloc = ctxt_string_to_location faddr testiaddr in
1555+
let testaddr = testloc#i in
1556+
let testinstr =
1557+
fail_tvalue
1558+
(trerror_record
1559+
(LBLOCK [
1560+
STR "FnDictionary: predicate assignment"; floc#ia#toPretty]))
1561+
(get_arm_assembly_instruction testaddr) in
1562+
let agg = get_aggregate floc#ia in
1563+
(match agg#kind with
1564+
| ARMPredicateAssignment (inverse, dstop) ->
1565+
let (_, optpredicate, _) =
1566+
arm_conditional_expr
1567+
~condopc:instr#get_opcode
1568+
~testopc:testinstr#get_opcode
1569+
~condloc:floc#l
1570+
~testloc:testloc in
1571+
let (tags, args) =
1572+
(match optpredicate with
1573+
| Some p ->
1574+
let p = if inverse then XOp (XLNot, [p]) else p in
1575+
let lhs = dstop#to_variable floc in
1576+
let rdefs = get_all_rdefs p in
1577+
let xp = rewrite_expr p in
1578+
let (tagstring, args) =
1579+
mk_instrx_data
1580+
~vars:[lhs]
1581+
~xprs:[p; xp]
1582+
~rdefs
1583+
~uses:[get_def_use lhs]
1584+
~useshigh:[get_def_use_high lhs]
1585+
() in
1586+
([tagstring], args)
1587+
| _ ->
1588+
([], [])) in
1589+
let dependents =
1590+
List.map (fun d ->
1591+
(make_i_location floc#l d#get_address)#ci) agg#instrs in
1592+
let tags = tags @ ["subsumes"] @ dependents in
1593+
(tags, args)
1594+
| _ ->
1595+
([], []))
1596+
else
1597+
([], [])
1598+
15491599
| Move _ when (Option.is_some instr#is_in_aggregate) ->
15501600
(match instr#is_in_aggregate with
15511601
| Some va ->

CodeHawk/CHB/bchlibarm32/bCHFnARMTypeConstraints.ml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ open BCHBCFiles
4242
open BCHBCTypePretty
4343
open BCHBCTypes
4444
open BCHBCTypeUtil
45-
open BCHConstantDefinitions
4645
open BCHCPURegisters
4746
open BCHDoubleword
4847
open BCHFloc
@@ -228,8 +227,8 @@ object (self)
228227

229228
(match getopt_global_address (rn#to_expr floc) with
230229
| Some gaddr ->
231-
if is_in_global_arrayvar gaddr then
232-
(match (get_arrayvar_base_offset gaddr) with
230+
if BCHConstantDefinitions.is_in_global_arrayvar gaddr then
231+
(match (BCHConstantDefinitions.get_arrayvar_base_offset gaddr) with
233232
| Some _ ->
234233
let rmdefs = get_variable_rdefs (rm#to_variable floc) in
235234
let rmreg = rm#to_register in
@@ -544,8 +543,8 @@ object (self)
544543
assign the type of that field to the destination register. *)
545544
(match getopt_global_address (memop#to_address floc) with
546545
| Some gaddr ->
547-
if is_in_global_structvar gaddr then
548-
match (get_structvar_base_offset gaddr) with
546+
if BCHConstantDefinitions.is_in_global_structvar gaddr then
547+
match (BCHConstantDefinitions.get_structvar_base_offset gaddr) with
549548
| Some (_, Field ((fname, fckey), NoOffset)) ->
550549
let compinfo = bcfiles#get_compinfo fckey in
551550
let finfo = get_compinfo_field compinfo fname in
@@ -598,8 +597,8 @@ object (self)
598597
assign that array type to the destination register. *)
599598
(match getopt_global_address (memop#to_expr floc) with
600599
| Some gaddr ->
601-
if is_in_global_arrayvar gaddr then
602-
(match (get_arrayvar_base_offset gaddr) with
600+
if BCHConstantDefinitions.is_in_global_arrayvar gaddr then
601+
(match (BCHConstantDefinitions.get_arrayvar_base_offset gaddr) with
603602
| Some (_, offset, bty) ->
604603
(match offset with
605604
| Index (Const (CInt (i64, _, _)), NoOffset) ->

0 commit comments

Comments
 (0)