From d8dddff8e9f49851b86627b80f189d08378ff10c Mon Sep 17 00:00:00 2001 From: gitoleg Date: Thu, 31 May 2018 09:58:27 -0400 Subject: [PATCH] added powerpc tests (#838) --- lib_test/powerpc/.merlin | 3 + lib_test/powerpc/powerpc_add_tests.ml | 358 ++++++++++++ lib_test/powerpc/powerpc_arith_tests.ml | 568 ++++++++++++++++++ lib_test/powerpc/powerpc_branch_tests.ml | 467 +++++++++++++++ lib_test/powerpc/powerpc_compare_tests.ml | 189 ++++++ lib_test/powerpc/powerpc_cr_tests.ml | 150 +++++ lib_test/powerpc/powerpc_load_tests.ml | 477 ++++++++++++++++ lib_test/powerpc/powerpc_logical_tests.ml | 636 +++++++++++++++++++++ lib_test/powerpc/powerpc_move_tests.ml | 94 +++ lib_test/powerpc/powerpc_rotate_tests.ml | 311 ++++++++++ lib_test/powerpc/powerpc_shift_tests.ml | 276 +++++++++ lib_test/powerpc/powerpc_store_tests.ml | 331 +++++++++++ lib_test/powerpc/powerpc_tests_helpers.ml | 491 ++++++++++++++++ lib_test/powerpc/powerpc_tests_helpers.mli | 91 +++ lib_test/powerpc/run_powerpc_tests.ml | 29 + oasis/powerpc | 32 ++ 16 files changed, 4503 insertions(+) create mode 100644 lib_test/powerpc/.merlin create mode 100644 lib_test/powerpc/powerpc_add_tests.ml create mode 100644 lib_test/powerpc/powerpc_arith_tests.ml create mode 100644 lib_test/powerpc/powerpc_branch_tests.ml create mode 100644 lib_test/powerpc/powerpc_compare_tests.ml create mode 100644 lib_test/powerpc/powerpc_cr_tests.ml create mode 100644 lib_test/powerpc/powerpc_load_tests.ml create mode 100644 lib_test/powerpc/powerpc_logical_tests.ml create mode 100644 lib_test/powerpc/powerpc_move_tests.ml create mode 100644 lib_test/powerpc/powerpc_rotate_tests.ml create mode 100644 lib_test/powerpc/powerpc_shift_tests.ml create mode 100644 lib_test/powerpc/powerpc_store_tests.ml create mode 100644 lib_test/powerpc/powerpc_tests_helpers.ml create mode 100644 lib_test/powerpc/powerpc_tests_helpers.mli create mode 100644 lib_test/powerpc/run_powerpc_tests.ml diff --git a/lib_test/powerpc/.merlin b/lib_test/powerpc/.merlin new file mode 100644 index 000000000..68616e3b5 --- /dev/null +++ b/lib_test/powerpc/.merlin @@ -0,0 +1,3 @@ +S . +B ../../_build/lib_test/powerpc +REC diff --git a/lib_test/powerpc/powerpc_add_tests.ml b/lib_test/powerpc/powerpc_add_tests.ml new file mode 100644 index 000000000..57a52cd48 --- /dev/null +++ b/lib_test/powerpc/powerpc_add_tests.ml @@ -0,0 +1,358 @@ +open Core_kernel.Std +open Bap.Std +open OUnit2 + +open Powerpc_tests_helpers + +let addi arch ctxt = + let bytes = "\x38\x21\x00\x10" in (** addi r1, r1, 16 *) + let r1 = find_gpr arch "R1" in + let width = arch_width arch in + let init = Bil.[ + r1 := int (Word.of_int ~width 26); + ] in + let expected = Word.of_int ~width 42 in + check_gpr init bytes r1 expected arch ctxt + +let addi_zero_op arch ctxt = + let bytes = "\x38\x20\x00\x10" in (** addi r1, 0, 16 OR li r1, 16 *) + let r1 = find_gpr arch "R1" in + let width = arch_width arch in + let expected = Word.of_int ~width 16 in + check_gpr [] bytes r1 expected arch ctxt + +let addis arch ctxt = + let bytes = "\x3f\xde\x00\x02" in (** addis r30, r30, 2 *) + let r30 = find_gpr arch "R30" in + let width = arch_width arch in + let init = Bil.[ + r30 := int (Word.of_int ~width 42); + ] in + let r = 42 + (2 lsl 16) in + let expected = Word.of_int ~width r in + check_gpr init bytes r30 expected arch ctxt + +let addis_zero_op arch ctxt = + let bytes = "\x3f\xc0\x00\x02" in (** addis r30, 0, 2 OR lis r30,1 *) + let r30 = find_gpr arch "R30" in + let width = arch_width arch in + let r = 2 lsl 16 in + let expected = Word.of_int ~width r in + check_gpr [] bytes r30 expected arch ctxt + +let add arch ctxt = + let bytes = "\x7d\x62\x5a\x14" in (** add r11, r2, r11 *) + let r2 = find_gpr arch "R2" in + let r11 = find_gpr arch "R11" in + let width = arch_width arch in + let x = Word.of_int ~width 34 in + let y = Word.of_int ~width 8 in + let init = Bil.[ + r2 := int x; + r11 := int y; + ] in + let expected = Word.of_int ~width 42 in + check_gpr init bytes r11 expected arch ctxt + +let addic arch _ctxt = + let bytes = "\x30\x21\x00\x10" in (** addic r1, r1, 16 *) + let r1 = find_gpr arch "R1" in + let width = arch_width arch in + let x = Word.of_int ~width 0x0fffffff0 in + let init = Bil.[ + r1 := int x; + ] in + let expected = match arch with + | `ppc -> Word.zero width + | _ -> Word.of_int ~width 0x00000001_00000000 in + let ctxt = eval init bytes arch in + let r1_value = lookup_var ctxt r1 in + let ca_value = lookup_var ctxt ca in + let ca32_value = lookup_var ctxt ca32 in + let ca_expected = match arch with + | `ppc -> Word.b1 + | _ -> Word.b0 in + assert_bool "addic failed: result" (is_equal_words expected r1_value); + assert_bool "addic failed: ca32" (is_equal_words Word.b1 ca32_value); + assert_bool "addic failed: ca" (is_equal_words ca_expected ca_value) + +let addc arch _ctxt = + let bytes = "\x7d\x62\x58\x14" in (** addc r11, r2, r11 *) + let r2 = find_gpr arch "R2" in + let r11 = find_gpr arch "R11" in + let width = arch_width arch in + let x = Word.of_int ~width 0x0fffffff0 in + let init = Bil.[ + r2 := int x; + r11 := int (Word.of_int ~width 16); + ] in + let expected = match arch with + | `ppc -> Word.zero width + | _ -> Word.of_int ~width 0x00000001_00000000 in + let ctxt = eval init bytes arch in + let r11_value = lookup_var ctxt r11 in + let ca_value = lookup_var ctxt ca in + let ca32_value = lookup_var ctxt ca32 in + let ca_expected = match arch with + | `ppc -> Word.b1 + | _ -> Word.b0 in + assert_bool "addc failed: result" (is_equal_words expected r11_value); + assert_bool "addc failed: ca32" (is_equal_words Word.b1 ca32_value); + assert_bool "addc failed: ca" (is_equal_words ca_expected ca_value) + +let adde arch _ctxt = + let bytes = "\x7c\x21\x81\x14" in (** adde r1, r1, r16 *) + let r1 = find_gpr arch "R1" in + let r16 = find_gpr arch "R16" in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xfffffff0L in + let init = Bil.[ + r1 := int x; + r16 := int (Word.of_int ~width 15); + ca := int Word.b1; + ] in + let ctxt = eval init bytes arch in + let r1_value = lookup_var ctxt r1 in + let ca_value = lookup_var ctxt ca in + let ca32_value = lookup_var ctxt ca32 in + let expected, ca_expected = match arch with + | `ppc -> Word.zero width, Word.b1 + | _ -> Word.of_int ~width:64 0x00000001_00000000, Word.b0 in + assert_bool "adde failed: result" (is_equal_words expected r1_value); + assert_bool "adde failed: ca32" (is_equal_words Word.b1 ca32_value); + assert_bool "adde failed: ca" (is_equal_words ca_expected ca_value) + +let addme arch _ctxt = + let bytes = "\x7c\x22\x01\xd4" in (** addme r1, r2 *) + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xffffffffL in + let init = Bil.[ + r2 := int x; + ca := int Word.b1; + ] in + let ctxt = eval init bytes arch in + let r1_value = lookup_var ctxt r1 in + let ca_value = lookup_var ctxt ca in + let ca32_value = lookup_var ctxt ca32 in + let expected = Word.of_int64 ~width 0xffffffffL in + assert_bool "addme failed: result" (is_equal_words expected r1_value); + assert_bool "addme failed: ca32" (is_equal_words Word.b0 ca32_value); + assert_bool "addme failed: ca" (is_equal_words Word.b0 ca_value) + +let addze arch _ctxt = + let bytes = "\x7c\x22\x01\x94" in (** addze r1, r2 *) + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let width = arch_width arch in + let x = match arch with + | `ppc -> Word.of_int64 ~width 0xffffffffL + | _ -> Word.of_int64 0xffffffff_ffffffffL in + let init = Bil.[ + r2 := int x; + ca := int Word.b1; + ] in + let ctxt = eval init bytes arch in + let r1_value = lookup_var ctxt r1 in + let ca_value = lookup_var ctxt ca in + let ca32_value = lookup_var ctxt ca32 in + let expected = Word.of_int ~width 0x0 in + assert_bool "addze failed: result" (is_equal_words expected r1_value); + assert_bool "addze failed: ca32" (is_equal_words Word.b1 ca32_value); + assert_bool "addze failed: ca" (is_equal_words Word.b1 ca_value) + +let add_dot arch _ctxt = + let bytes = "\x7d\x62\x5a\x15" in (** add. r11, r2, r11 *) + let r2 = find_gpr arch "R2" in + let r11 = find_gpr arch "R11" in + let width = arch_width arch in + let x = Word.of_int ~width 34 in + let y = Word.of_int ~width 8 in + let init = Bil.[ + r2 := int x; + r11 := int y; + ] in + let expected = Word.of_int ~width 42 in + let ctxt = eval init bytes arch in + let r11_value = lookup_var ctxt r11 in + let nf_value = lookup_var ctxt nf in + let pf_value = lookup_var ctxt pf in + let zf_value = lookup_var ctxt zf in + assert_bool "add. failed: result" (is_equal_words expected r11_value); + assert_bool "add. failed: nf" (is_equal_words Word.b0 nf_value); + assert_bool "add. failed: pf" (is_equal_words Word.b1 pf_value); + assert_bool "add. failed: zf" (is_equal_words Word.b0 zf_value) + +let addic_dot arch _ctxt = + let bytes = "\x34\x21\x00\x10" in (** addic. r1, r1, 16 *) + let r1 = find_gpr arch "R1" in + let width = arch_width arch in + let x = match arch with + | `ppc -> Word.of_int64 ~width 0xfffffff0L + | _ -> Word.of_int64 0xffffffff_fffffff0L in + let init = Bil.[ + r1 := int x; + ] in + let expected = Word.of_int ~width 0 in + let ctxt = eval init bytes arch in + let r1_value = lookup_var ctxt r1 in + let ca_value = lookup_var ctxt ca in + let ca32_value = lookup_var ctxt ca32 in + let nf_value = lookup_var ctxt nf in + let pf_value = lookup_var ctxt pf in + let zf_value = lookup_var ctxt zf in + assert_bool "addic. failed: result" (is_equal_words expected r1_value); + assert_bool "addic. failed: ca32" (is_equal_words Word.b1 ca32_value); + assert_bool "addic. failed: ca" (is_equal_words Word.b1 ca_value); + assert_bool "addic. failed: nf" (is_equal_words Word.b0 nf_value); + assert_bool "addic. failed: pf" (is_equal_words Word.b0 pf_value); + assert_bool "addic. failed: zf" (is_equal_words Word.b1 zf_value) + +let addc_dot arch _ctxt = + let bytes = "\x7d\x62\x58\x15" in (** addc. r11, r2, r11 *) + let r2 = find_gpr arch "R2" in + let r11 = find_gpr arch "R11" in + let width = arch_width arch in + let x,y,expected = match arch with + | `ppc -> + Word.of_int64 ~width 0x0ffffff0L, + Word.of_int64 ~width 0xf000000fL, + Word.of_int64 ~width 0xffffffffL + | _ -> + Word.of_int64 0x0fffffff_fffffff0L, + Word.of_int64 0xf0000000_0000000fL, + Word.of_int64 0xffffffff_ffffffffL in + let init = Bil.[ + r2 := int x; + r11 := int y; + ] in + let ctxt = eval init bytes arch in + let r11_value = lookup_var ctxt r11 in + let ca_value = lookup_var ctxt ca in + let ca32_value = lookup_var ctxt ca32 in + let nf_value = lookup_var ctxt nf in + let pf_value = lookup_var ctxt pf in + let zf_value = lookup_var ctxt zf in + assert_bool "addc. failed: result" (is_equal_words expected r11_value); + assert_bool "addc. failed: ca32" (is_equal_words Word.b0 ca32_value); + assert_bool "addc. failed: ca" (is_equal_words Word.b0 ca_value); + assert_bool "addc. failed: nf" (is_equal_words Word.b1 nf_value); + assert_bool "addc. failed: pf" (is_equal_words Word.b0 pf_value); + assert_bool "addc. failed: zf" (is_equal_words Word.b0 zf_value) + +let adde_dot arch _ctxt = + let bytes = "\x7c\x21\x81\x15" in (** adde. r1, r1, r16 *) + let r1 = find_gpr arch "R1" in + let r16 = find_gpr arch "R16" in + let width = arch_width arch in + let x = Word.of_int64 ~width 0x0ffffff0L in + let y = Word.of_int64 ~width 0xf000000eL in + let init = Bil.[ + r1 := int x; + r16 := int y; + ca := int Word.b1; + ] in + let ctxt = eval init bytes arch in + let r1_value = lookup_var ctxt r1 in + let ca_value = lookup_var ctxt ca in + let ca32_value = lookup_var ctxt ca32 in + let expected = Word.of_int64 ~width 0xffffffffL in + let nf_expected, pf_expected = match arch with + | `ppc -> Word.b1, Word.b0 + | `ppc64 -> Word.b0, Word.b1 + | _ -> failwith "PowerPC only expected" in + let nf_value = lookup_var ctxt nf in + let pf_value = lookup_var ctxt pf in + let zf_value = lookup_var ctxt zf in + assert_bool "adde. failed: result" (is_equal_words expected r1_value); + assert_bool "adde. failed: ca32" (is_equal_words Word.b0 ca32_value); + assert_bool "adde. failed: ca" (is_equal_words Word.b0 ca_value); + assert_bool "adde. failed: nf" (is_equal_words nf_expected nf_value); + assert_bool "adde. failed: pf" (is_equal_words pf_expected pf_value); + assert_bool "adde. failed: zf" (is_equal_words Word.b0 zf_value) + +let addme_dot arch _ctxt = + let bytes = "\x7c\x22\x01\xd5" in (** addme. r1, r2 *) + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let width = arch_width arch in + let x = Word.one width in + let init = Bil.[ + r2 := int x; + ca := int Word.b0; + ] in + let ctxt = eval init bytes arch in + let r1_value = lookup_var ctxt r1 in + let ca_value = lookup_var ctxt ca in + let ca32_value = lookup_var ctxt ca32 in + let expected = Word.zero width in + let cf_expected = match arch with + | `ppc -> Word.b1 + | _ -> Word.b1 in + let nf_value = lookup_var ctxt nf in + let pf_value = lookup_var ctxt pf in + let zf_value = lookup_var ctxt zf in + assert_bool "addme. failed: result" (is_equal_words expected r1_value); + assert_bool "addme. failed: ca32" (is_equal_words Word.b1 ca32_value); + assert_bool "addme. failed: ca" (is_equal_words cf_expected ca_value); + assert_bool "addme. failed: nf" (is_equal_words Word.b0 nf_value); + assert_bool "addme. failed: pf" (is_equal_words Word.b0 pf_value); + assert_bool "addme. failed: zf" (is_equal_words Word.b1 zf_value) + +let addze_dot arch ctxt = + let bytes = "\x7c\x22\x01\x95" in (** addze. r1, r2 *) + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let width = arch_width arch in + let x = match arch with + | `ppc -> Word.of_int64 ~width 0xffffffffL + | _ -> Word.of_int64 0xffffffff_ffffffffL in + let init = Bil.[ + r2 := int x; + ca := int Word.b1; + ] in + let ctxt = eval init bytes arch in + let r1_value = lookup_var ctxt r1 in + let ca_value = lookup_var ctxt ca in + let ca32_value = lookup_var ctxt ca32 in + let expected = Word.zero width in + assert_bool "addze. failed: result" (is_equal_words expected r1_value); + assert_bool "addze. failed: ca32" (is_equal_words Word.b1 ca32_value); + assert_bool "addze. failed: ca" (is_equal_words Word.b1 ca_value) + +let suite = "add" >::: [ + "addi32" >:: addi `ppc; + "addi32_0" >:: addi_zero_op `ppc; + "addis32" >:: addis `ppc; + "addis32_0" >:: addis_zero_op `ppc; + "add32" >:: add `ppc; + "addic32" >:: addic `ppc; + "addc32" >:: addc `ppc; + "adde32" >:: adde `ppc; + "addme32" >:: addme `ppc; + "addze32" >:: addze `ppc; + "add.32" >:: add_dot `ppc; + "addic.32" >:: addic_dot `ppc; + "addc.32" >:: addc_dot `ppc; + "adde.32" >:: adde_dot `ppc; + "addme.32" >:: addme_dot `ppc; + "addze.32" >:: addze_dot `ppc; + + "addi64" >:: addi `ppc64; + "addi64_0" >:: addi_zero_op `ppc64; + "addis64" >:: addis `ppc64; + "addis64_0" >:: addis_zero_op `ppc64; + "add64" >:: add `ppc64; + "addic64" >:: addic `ppc64; + "addc64" >:: addc `ppc64; + "adde64" >:: adde `ppc64; + "addme64" >:: addme `ppc64; + "addze64" >:: addze `ppc64; + "add.64" >:: add_dot `ppc64; + "addic.64" >:: addic_dot `ppc64; + "addc.64" >:: addc_dot `ppc64; + "adde.64" >:: adde_dot `ppc64; + "addme.64" >:: addme_dot `ppc64; + "addze.64" >:: addze_dot `ppc64; + ] diff --git a/lib_test/powerpc/powerpc_arith_tests.ml b/lib_test/powerpc/powerpc_arith_tests.ml new file mode 100644 index 000000000..157c6a785 --- /dev/null +++ b/lib_test/powerpc/powerpc_arith_tests.ml @@ -0,0 +1,568 @@ +open Core_kernel.Std +open Bap.Std +open OUnit2 + +open Powerpc_tests_helpers + +let extend ?(upto=64) x = Word.extract_exn ~hi:(upto - 1) x +let low ?(len=32) x = Word.extract_exn ~hi:(len - 1) x + +let high ?(len=32) x = + let width = Word.bitwidth x in + let hi = width - 1 in + let lo = width - len in + Word.extract_exn ~hi ~lo x + +let neg arch ctxt = + let name = "NEG" in + let bytes = make_insn ~name `XO [31; 1; 2; 0; 0; 104; 0] in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let width = arch_width arch in + let x = match arch with + | `ppc -> Word.of_int64 ~width 0x80000000L + | _ -> + Word.of_int64 0x80000000_00000000L in + let init = Bil.[ + r2 := int x; + ] in + check_gpr init bytes r1 x arch ctxt + +let subf arch ctxt = + let name = "SUBF" in + let bytes = make_insn ~name `XO [31; 1; 2; 3; 0; 40; 0] in + let width = arch_width arch in + let x = match arch with + | `ppc -> Word.of_int64 ~width 12345678L + | _ -> Word.of_int64 0xABCDEF42_12345678L in + let y = Word.of_int ~width 0x42 in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let init = Bil.[ + r3 := int x; + r2 := int y; + ] in + let expected = Word.(x - y) in + check_gpr init bytes r1 expected arch ctxt + +let subfic arch _ctxt = + let name = "SUBFIC" in + let x = 42 in + let bytes = make_insn ~name `D [8; 1; 2; x] in + let width = arch_width arch in + let x = Word.of_int ~width x in + let y = Word.of_int ~width 43 in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let init = Bil.[ + r2 := int y; + ] in + let expected = Word.(x - y) in + let ctxt = eval init bytes arch in + let r1_val = lookup_var ctxt r1 in + let ca_val = lookup_var ctxt ca in + let ca32_val = lookup_var ctxt ca32 in + let ca_exp = Word.b1 in + let ca32_exp = Word.b1 in + assert_bool "subfic failed, result" (is_equal_words expected r1_val); + assert_bool "subfic failed, ca" (is_equal_words ca_exp ca_val); + assert_bool "subfic failed, ca32" (is_equal_words ca32_exp ca32_val) + +let subfc arch ctxt = + let name = "SUBFC" in + let bytes = make_insn ~name `XO [31; 1; 2; 3; 0; 8; 0] in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xABCDEF42_12345678L in + let y = Word.of_int ~width 0x42 in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let init = Bil.[ + r3 := int x; + r2 := int y; + ] in + let expected = Word.(x - y) in + check_gpr init bytes r1 expected arch ctxt + +let subfe arch ctxt = + let name = "SUBFE" in + let bytes = make_insn ~name `XO [31; 1; 2; 3; 0; 136; 0] in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xABCDEF42_12345678L in + let y = Word.of_int ~width 0x42 in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let init = Bil.[ + r3 := int x; + r2 := int y; + ca := int Word.b1 + ] in + let expected = Word.((lnot y) + x + b1) in + check_gpr init bytes r1 expected arch ctxt + +let subfe arch ctxt = + let name = "SUBFE" in + let bytes = make_insn ~name `XO [31; 1; 2; 3; 0; 136; 0] in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xABCDEF42_12345678L in + let y = Word.of_int ~width 0x42 in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let init = Bil.[ + r3 := int x; + r2 := int y; + ca := int Word.b1 + ] in + let expected = Word.((lnot y) + x + b1) in + check_gpr init bytes r1 expected arch ctxt + +let subfme arch ctxt = + let name = "SUBFME" in + let bytes = make_insn ~name `XO [31; 1; 2; 0; 0; 232; 0] in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xABCDEF42_12345678L in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let init = Bil.[ + r2 := int x; + ca := int Word.b1 + ] in + let expected = Word.(lnot x) in + check_gpr init bytes r1 expected arch ctxt + +let subfze arch ctxt = + let name = "SUBFZE" in + let bytes = make_insn ~name `XO [31; 1; 2; 0; 0; 200; 0] in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xABCDEF42_12345678L in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let init = Bil.[ + r2 := int x; + ca := int Word.b1 + ] in + let expected = Word.((lnot x) + b1) in + check_gpr init bytes r1 expected arch ctxt + +let mulli arch ctxt = + let name = "MULLI" in + let y = 0b1_1111_1111_1111 in + let bytes = make_insn ~name `D [7; 1; 2; y] in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xABCDEFAA_BBCDEDAAL in + let y = Word.of_int ~width y in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let init = Bil.[ + r2 := int x; + ] in + let expected = Word.(x * y) in + check_gpr init bytes r1 expected arch ctxt + +let mulhw arch ctxt = + let name = "MULHW" in + let bytes = make_insn ~name `XO [31; 1; 2; 3; 0; 75; 0] in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xABCDEFAA_BBCDEDAAL in + let y = Word.of_int64 ~width 0x00000000_00004242L in + let z = Word.of_int64 ~width 0xFFFFFFFF_ABCDEFAAL in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let init = Bil.[ + r1 := int x; + r2 := int y; + r3 := int z; + ] in + let expected = + let y = extend (Word.signed y) in + let z = extend (Word.signed z) in + Word.signed (high Word.(y * z)) in + let expected = match arch with + | `ppc -> expected + | _ -> extend expected in + check_gpr init bytes r1 expected arch ctxt + +let mulhwu arch ctxt = + let name = "MULHWU" in + let bytes = make_insn ~name `XO [31; 1; 2; 3; 0; 11; 0] in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xABCDEFAA_BBCDEDAAL in + let y = Word.of_int64 ~width 0x4242L in + let z = Word.of_int64 ~width 0xABCDEFAAL in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let init = Bil.[ + r1 := int x; + r2 := int y; + r3 := int z; + ] in + let expected = + let y = extend y in + let z = extend z in + high Word.(y * z) in + let expected = match arch with + | `ppc -> expected + | _ -> extend expected in + check_gpr init bytes r1 expected arch ctxt + +let mullw arch ctxt = + let name = "MULLW" in + let bytes = make_insn ~name `XO [31; 1; 2; 3; 0; 235; 0] in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xABCDEFAA_BBCDEDAAL in + let y = Word.of_int64 ~width 0x12345678_42424242L in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let init = Bil.[ + r2 := int x; + r3 := int y; + ] in + let expected = match arch with + | `ppc -> Word.(low x * low y) + | _ -> + let low x = extend (low x) in + Word.(low x * low y) in + check_gpr init bytes r1 expected arch ctxt + +let divw arch ctxt = + let name = "DIVW" in + let bytes = make_insn ~name `XO [31; 1; 2; 3; 0; 491; 0] in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xABCDEFAA_88888888L in + let y = Word.of_int64 ~width 0x12345678_44444444L in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let init = Bil.[ + r2 := int x; + r3 := int y; + ] in + let x = Word.signed (low x) in + let y = Word.signed (low y) in + let r = Word.(signed (x / y)) in + let expected = match arch with + | `ppc -> r + | _ -> extend r in + check_gpr init bytes r1 expected arch ctxt + +let divwu arch ctxt = + let name = "DIVWU" in + let bytes = make_insn ~name `XO [31; 1; 2; 3; 0; 459; 0] in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xABCDEFAA_88888888L in + let y = Word.of_int64 ~width 0x12345678_44444444L in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let init = Bil.[ + r2 := int x; + r3 := int y; + ] in + let r = Word.(low x / low y) in + let expected = match arch with + | `ppc -> r + | _ -> extend r in + check_gpr init bytes r1 expected arch ctxt + +let divwe arch ctxt = + let name = "DIVWE" in + let bytes = make_insn ~name `XO [31; 1; 2; 3; 0; 427; 0] in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xABCDEFAA_88888888L in + let y = Word.of_int64 ~width 0x12345678_44444444L in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let init = Bil.[ + r2 := int x; + r3 := int y; + ] in + let x = match arch with + | `ppc -> + Word.(signed (concat x (zero 32))) + | _ -> + Word.(signed (x lsl (Word.of_int64 32L))) in + let y = Word.signed (low y) in + let r = Word.signed (low Word.(x/y)) in + let expected = match arch with + | `ppc -> r + | _ -> extend r in + check_gpr init bytes r1 expected arch ctxt + +let divweu arch ctxt = + let name = "DIVWEU" in + let bytes = make_insn ~name `XO [31; 1; 2; 3; 0; 395; 0] in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xABCDEFAA_88888888L in + let y = Word.of_int64 ~width 0x12345678_44444444L in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let init = Bil.[ + r2 := int x; + r3 := int y; + ] in + let x = match arch with + | `ppc -> Word.concat x (Word.zero 32) + | _ -> Word.(x lsl (Word.of_int64 32L)) in + let y = low y in + let r = low Word.(x/y) in + let expected = match arch with + | `ppc -> r + | _ -> extend r in + check_gpr init bytes r1 expected arch ctxt + +let modsw arch ctxt = + let name = "MODSW" in + let bytes = make_insn ~name `X [31; 1; 2; 3; 779; 0] in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xABCDEFAB_CDEFABCDL in + let y = Word.of_int64 ~width 0x12345678_91234567L in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let init = Bil.[ + r2 := int x; + r3 := int y; + ] in + let x = Word.signed (low x) in + let y = Word.signed (low y) in + let r = Word.signed Word.(x mod y) in + let expected = match arch with + | `ppc -> r + | _ -> extend r in + check_gpr init bytes r1 expected arch ctxt + +let moduw arch ctxt = + let name = "MODUW" in + let bytes = make_insn ~name `X [31; 1; 2; 3; 267; 0] in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xABCDEFAB_CDEFABCDL in + let y = Word.of_int64 ~width 0x12345678_91234567L in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let init = Bil.[ + r2 := int x; + r3 := int y; + ] in + let r = Word.(low x mod low y) in + let expected = match arch with + | `ppc -> r + | _ -> extend r in + check_gpr init bytes r1 expected arch ctxt + +let mulld ctxt = + let arch = `ppc64 in + let name = "MULLD" in + let bytes = make_insn ~name `XO [31; 1; 2; 3; 0; 233; 0] in + let x = Word.of_int64 0xABCDEFAB_CDEFABCDL in + let y = Word.of_int64 0x12345678_91234567L in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let init = Bil.[ + r2 := int x; + r3 := int y; + ] in + let expected = Word.(x * y) in + check_gpr init bytes r1 expected arch ctxt + +let mulhd ctxt = + let arch = `ppc64 in + let name = "MULHD" in + let bytes = make_insn ~name `XO [31; 1; 2; 3; 0; 73; 0] in + let x = Word.of_int64 0xABCDEFAB_CDEFABCDL in + let y = Word.of_int64 0x12345678_91234567L in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let init = Bil.[ + r2 := int x; + r3 := int y; + ] in + let x = Word.signed x in + let y = Word.signed y in + let x = extend ~upto:128 x in + let y = extend ~upto:128 y in + let expected = high ~len:64 Word.(x * y) in + check_gpr init bytes r1 expected arch ctxt + +let mulhdu ctxt = + let arch = `ppc64 in + let name = "MULHDU" in + let bytes = make_insn ~name `XO [31; 1; 2; 3; 0; 9; 0] in + let x = Word.of_int64 0xABCDEFAB_CDEFABCDL in + let y = Word.of_int64 0x12345678_91234567L in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let init = Bil.[ + r2 := int x; + r3 := int y; + ] in + let x = extend ~upto:128 x in + let y = extend ~upto:128 y in + let expected = high ~len:64 Word.(x * y) in + check_gpr init bytes r1 expected arch ctxt + +let divd ctxt = + let arch = `ppc64 in + let name = "DIVD" in + let bytes = make_insn ~name `XO [31; 1; 2; 3; 0; 489; 0] in + let x = Word.of_int64 0xABCDEFAB_CDEFABCDL in + let y = Word.of_int64 0x12345678_91234567L in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let init = Bil.[ + r2 := int x; + r3 := int y; + ] in + let x = Word.signed x in + let y = Word.signed y in + let expected = Word.(x / y) in + check_gpr init bytes r1 expected arch ctxt + +let divdu ctxt = + let arch = `ppc64 in + let name = "DIVDU" in + let bytes = make_insn ~name `XO [31; 1; 2; 3; 0; 457; 0] in + let x = Word.of_int64 0xABCDEFAB_CDEFABCDL in + let y = Word.of_int64 0x12345678_91234567L in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let init = Bil.[ + r2 := int x; + r3 := int y; + ] in + let expected = Word.(x / y) in + check_gpr init bytes r1 expected arch ctxt + +let divde ctxt = + let arch = `ppc64 in + let name = "DIVDE" in + let bytes = make_insn ~name `XO [31; 1; 2; 3; 0; 425; 0] in + let x = Word.of_int64 0xABCDEFAB_CDEFABCDL in + let y = Word.of_int64 0x12345678_91234567L in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let init = Bil.[ + r2 := int x; + r3 := int y; + ] in + let shift = Word.of_int64 64L in + let x = extend ~upto:128 x in + let x = Word.(x lsl shift) in + let x = Word.signed x in + let expected = low ~len:64 Word.(x / y) in + check_gpr init bytes r1 expected arch ctxt + +let divdeu ctxt = + let arch = `ppc64 in + let name = "DIVDEU" in + let bytes = make_insn ~name `XO [31; 1; 2; 3; 0; 393; 0] in + let x = Word.of_int64 0xABCDEFAB_CDEFABCDL in + let y = Word.of_int64 0x12345678_91234567L in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let init = Bil.[ + r2 := int x; + r3 := int y; + ] in + let shift = Word.of_int64 64L in + let x = extend ~upto:128 x in + let x = Word.(x lsl shift) in + let expected = low ~len:64 Word.(x / y) in + check_gpr init bytes r1 expected arch ctxt + +let modsd ctxt = + let arch = `ppc64 in + let name = "MODSD" in + let bytes = make_insn ~name `X [31; 1; 2; 3; 777; 0] in + let x = Word.of_int64 0xABCDEFAB_CDEFABCDL in + let y = Word.of_int64 0x12345678_91234567L in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let init = Bil.[ + r2 := int x; + r3 := int y; + ] in + let x = Word.signed x in + let y = Word.signed y in + let expected = Word.(x mod y) in + check_gpr init bytes r1 expected arch ctxt + +let modud ctxt = + let arch = `ppc64 in + let name = "MODUD" in + let bytes = make_insn ~name `X [31; 1; 2; 3; 265; 0] in + let x = Word.of_int64 0xABCDEFAB_CDEFABCDL in + let y = Word.of_int64 0x12345678_91234567L in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let init = Bil.[ + r2 := int x; + r3 := int y; + ] in + let expected = Word.(x mod y) in + check_gpr init bytes r1 expected arch ctxt + +let suite = "arith" >::: [ + "neg" >:: neg `ppc; + "subf" >:: subf `ppc; + "subfic" >:: subfic `ppc; + "subfc" >:: subfc `ppc; + "subfe" >:: subfe `ppc; + "subme" >:: subfme `ppc; + "subze" >:: subfze `ppc; + "mulli" >:: mulli `ppc; + "mulhw" >:: mulhw `ppc; + "mulhwu" >:: mulhwu `ppc; + "mullw" >:: mullw `ppc; + "divw" >:: divw `ppc; + "divwu" >:: divwu `ppc; + "divwe" >:: divwe `ppc; + "divweu" >:: divweu `ppc; + "modsw" >:: modsw `ppc; + "moduw" >:: moduw `ppc; + + "neg 64" >:: neg `ppc64; + "subf 64" >:: subf `ppc64; + "subfic 64" >:: subfic `ppc64; + "subfc 64" >:: subfc `ppc64; + "subfe 64" >:: subfe `ppc64; + "subme 64" >:: subfme `ppc64; + "subze 64" >:: subfze `ppc64; + "mulli 64" >:: mulli `ppc64; + "mulhw 64" >:: mulhw `ppc64; + "mulhwu 64" >:: mulhwu `ppc64; + "mullw 64" >:: mullw `ppc64; + "divw 64" >:: divw `ppc64; + "divwu 64" >:: divwu `ppc64; + "divwe 64" >:: divwe `ppc64; + "divweu 64" >:: divweu `ppc64; + "modsw 64" >:: modsw `ppc64; + "moduw 64" >:: moduw `ppc64; + "mulld 64" >:: mulld; + "mulhd 64" >:: mulhd; + "mulhdu 64" >:: mulhdu; + "divd 64" >:: divd; + "divdu 64" >:: divdu; + "divde 64" >:: divde; + "divdeu 64" >:: divdeu; + "modsd 64" >:: modsd; + "modud 64" >:: modud; + + ] diff --git a/lib_test/powerpc/powerpc_branch_tests.ml b/lib_test/powerpc/powerpc_branch_tests.ml new file mode 100644 index 000000000..ebe360d25 --- /dev/null +++ b/lib_test/powerpc/powerpc_branch_tests.ml @@ -0,0 +1,467 @@ +open Core_kernel.Std +open Bap.Std +open OUnit2 + +open Powerpc_tests_helpers + +let typecheck bytes arch _ctxt = + let bil = get_bil arch bytes in + assert_bool "typecheck failed" (Result.is_ok bil) + +let check_pc name c expected = + match c#pc with + | Bil.Imm a -> + assert_bool + (sprintf "%s fail: addr is not equal to expected: %s <> %s" + name + (Addr.to_string a) + (Addr.to_string expected)) + (Addr.equal a expected) + | _ -> + assert_bool (sprintf "%s fail: pc is not a word" name) false + +let check_jmp_absence name c = + assert_bool (sprintf "%s fail: jmp occured" name) (c#pc = Bil.Bot) + +let addr_of_arch = function + | `ppc -> Word.of_int64 ~width:32 0xABCD42AAL + | `ppc64 -> Word.of_int64 0x0AAAAAAA_00000042L + | _ -> failwith "PowerPC only" + +let extract ~hi ~lo w = Word.extract_exn ~hi ~lo w + +let word_of_int arch x = + let width = Arch.addr_size arch |> Size.in_bits in + Word.of_int ~width x + +let branch name aa lk arch offs (_ctxt : test_ctxt)= + let bits = Size.in_bits @@ Arch.addr_size arch in + let addr = addr_of_arch arch in + let bytes = make_insn ~name ~arch `I [18; offs; aa; lk] in + let imm = + Word.(word_of_int arch offs lsl word_of_int arch 2) in + let expected = + if aa = 1 then imm + else (Word.(addr + imm)) in + let c = eval ~addr [] bytes arch in + check_pc name c expected; + if lk = 1 then + let next = Word.(word_of_int arch 4 + addr) in + let next = extract ~hi:(bits - 1) ~lo:0 next in + let err = sprintf "%s failed, LR is wrong!" name in + assert_bool err @@ is_equal_words next (lookup_var c (lr arch)) + +let b = branch "B" 0 0 +let ba = branch "BA" 1 0 +let bl = branch "BL" 0 1 +let bla = branch "BLA" 1 1 + +type bo = { + bo_field : int; + ctr_before : word; + ctr_after : word option; + cond_reg0 : word; + expect_jump : bool; +} + +let make_bo ?ctr_before ?ctr_after ?cond_reg0 ?(expect_jump = false) + bo_field arch = + let bits = Size.in_bits @@ Arch.addr_size arch in + let ctr_before = match ctr_before with + | None -> Word.zero bits + | Some x -> Word.of_int ~width:bits x in + let ctr_after = + Option.map ~f:(fun x -> Word.of_int ~width:bits x) ctr_after in + let cond_reg0 = match cond_reg0 with + | None -> Word.b0 + | Some x -> Word.of_bool (x = 1) in + {bo_field; ctr_before; ctr_after; cond_reg0; expect_jump;} + +let counter_unchanged = make_bo ~ctr_before:42 ~cond_reg0:1 ~ctr_after:42 0b00100 +let counter_decremented = make_bo ~ctr_before:42 ~cond_reg0:1 ~ctr_after:41 0b00000 +let jmp_anyway = make_bo ~expect_jump:true 0b10100 + +(** cond: bo3 = CR0 = 1; ctr: bo1 = 1 and ctr = 0 *) +let cond_ctr_ok_1 = make_bo ~ctr_before:1 ~cond_reg0:1 ~expect_jump:true 0b01010 + +(** cond: bo3 = CR0 = 0; ctr: bo1 = 0 and ctr <> 0 *) +let cond_ctr_ok_2 = make_bo ~ctr_before:42 ~cond_reg0:0 ~expect_jump:true 0b00000 + +(** cond: bo3 = CR0 = 1; ctr: bo1 = 0 and ctr <> 0 *) +let cond_ctr_ok_3 = make_bo ~ctr_before:42 ~cond_reg0:1 ~expect_jump:true 0b01000 + +(** cond: bo3 = CR0 = 0; ctr: bo1 = 1 and ctr = 0 *) +let cond_ctr_ok_4 = make_bo ~ctr_before:1 ~cond_reg0:0 ~expect_jump:true 0b00010 + +(** cond: bo3 = CR0 = 0; ctr: bo1 = 1 and ctr <> 0 *) +let cond_ok_ctr_not_1 = make_bo ~ctr_before:42 ~cond_reg0:0 0b00010 + +(** cond: bo3 = 1; CR0 = 0; ctr: bo1 = 1 and ctr <> 0 *) +let cond_not_ctr_ok_1 = make_bo ~ctr_before:42 ~cond_reg0:0 0b01010 + +(** cond: bo3 = CR0 = 0; *) +let cond_ok = make_bo ~cond_reg0:0 ~expect_jump:true 0b00010 + +(** cond: bo3 = 1; CR0 = 0; *) +let cond_not = make_bo ~cond_reg0:0 0b01010 + +let bcx name aa lk arch imm case (_ctxt : test_ctxt) = + let case = case arch in + let bits = Size.in_bits @@ Arch.addr_size arch in + let bytes = make_insn ~name ~arch `B + [16; case.bo_field; 0; imm; aa; lk] in + let cr0 = cr_bit 0 in + let ctr = ctr arch in + let init = Bil.[ + cr0 := int case.cond_reg0; + ctr := int case.ctr_before; + ] in + let addr = addr_of_arch arch in + let c = eval ~addr init bytes arch in + if case.expect_jump then + let imm = Word.(word_of_int arch imm lsl word_of_int arch 2) in + let expected = + if aa = 1 then imm + else Word.(addr + imm) in + check_pc name c expected + else check_jmp_absence name c; + let () = match case.ctr_after with + | None -> () + | Some x -> + assert_bool (sprintf "%s failed" name) + @@ is_equal_words x (lookup_var c ctr) in + if lk = 1 then + let next = Word.(of_int ~width:bits 4 + addr) in + let next = extract ~hi:(bits - 1) ~lo:0 next in + assert_bool (sprintf "%s failed to check LR value" name) + @@ is_equal_words next (lookup_var c (lr arch)) + +let bc = bcx "gBC" 0 0 +let bca = bcx "gBCA" 1 0 +let bcl = bcx "gBCL" 0 1 +let bcla = bcx "gBCLA" 1 1 + +let bcXrX name opt_opcode lk reg arch case (_ctxt : test_ctxt) = + let case = case arch in + let reg = reg arch in + let bits = Size.in_bits @@ Arch.addr_size arch in + let cr_num = 31 in + let bytes = make_insn ~name ~arch `XL + [19; case.bo_field; cr_num; 0; 0; opt_opcode; lk ] in + let cr0 = cr_bit cr_num in + let addr = addr_of_arch arch in + let ctr = ctr arch in + let init = Bil.[ + cr0 := int case.cond_reg0; + ctr := int case.ctr_before; + ] in + let init = init @ Bil.[reg := cast unsigned bits (int addr)] in + let c = eval ~addr init bytes arch in + if case.expect_jump then + let expected_addr = + let left = extract ~hi:(bits-1) ~lo:2 addr in + let right = Word.zero 2 in + Word.concat left right in + check_pc name c expected_addr + else check_jmp_absence name c; + let () = match case.ctr_after with + | None -> () + | Some x -> + assert_bool (sprintf "%s ctr check failed" name) @@ is_equal_words x (lookup_var c ctr) in + if lk = 1 then + let next = Word.(of_int ~width:bits 4 + addr) in + let next = extract ~hi:(bits - 1) ~lo:0 next in + assert_bool (sprintf "%s failed to check LR value" name) + @@ is_equal_words next (lookup_var c (lr arch)) + +let bclr = bcXrX "gBCLR" 16 0 lr +let bclrl = bcXrX "gBCLRL" 16 1 lr +let bcctr = bcXrX "gBCCTR" 528 0 ctr +let bcctrl = bcXrX "gBCCTRL" 528 1 ctr + +(* will add as soon bctar will apear in llvm *) +let bctar = bcXrX "bctar" 560 0 tar +let bctarl = bcXrX "bctarl" 560 1 tar + +let bdnz ~jmp arch (_ctxt : test_ctxt) = + let imm = 42 in + let bits = Size.in_bits @@ Arch.addr_size arch in + let opcode = Word.of_int ~width:6 16 in + let bo = Word.of_int ~width:5 0b10000 in + let bi = Word.of_int ~width:5 0 in + let bd = Word.of_int ~width:14 imm in + let fin = Word.of_int ~width:2 0 in + let bytes = make_bytes [opcode; bo; bi; bd; fin] in + let ctr_val = + if jmp then Word.of_int ~width:bits 42 + else Word.one bits in + let ctr = ctr arch in + let init = Bil.[ctr := int ctr_val] in + let addr = addr_of_arch arch in + let c = eval ~addr init bytes arch in + let imm = Word.of_int ~width:bits (imm lsl 2) in + if jmp then + let expected = Word.(addr + imm) in + check_pc "bdnz" c expected + else + check_jmp_absence "bdzf" c; + let x = Word.pred ctr_val in + assert_bool "bdnz cnt check failed" @@ is_equal_words x (lookup_var c ctr) + +let bdnzlr ~jmp arch (_ctxt : test_ctxt) = + let bits = Size.in_bits @@ Arch.addr_size arch in + let opcode = Word.of_int ~width:6 19 in + let bo = Word.of_int ~width:5 0b10000 in + let bi = Word.of_int ~width:5 0 in + let no_matter = Word.zero 3 in + let bh = Word.zero 2 in + let opt_opcode = Word.of_int ~width:10 16 in + let fin = Word.of_int ~width:1 0 in + let bytes = make_bytes [opcode; bo; bi; no_matter; bh; opt_opcode; fin] in + let ctr_val = + if jmp then Word.of_int ~width:bits 42 + else Word.one bits in + let addr = addr_of_arch arch in + let ctr = ctr arch in + let lr = lr arch in + let init = Bil.[ + ctr := int ctr_val; + lr := cast unsigned bits (int addr); + ] in + let c = eval ~addr init bytes arch in + if jmp then + let mask = Word.(ones bits lsl of_int ~width:bits 2) in + let expected = Word.(addr land mask) in + check_pc "bdnzlr" c expected + else + check_jmp_absence "bdnzlr" c; + let x = Word.pred ctr_val in + assert_bool "bdnzlr cnt check failed" @@ is_equal_words x (lookup_var c ctr) + +let pos = 42 +let neg = -42 + +let suite = "branch" >::: [ + "b32 +" >:: b `ppc pos; + "b32 -" >:: b `ppc neg; + "ba32 +" >:: ba `ppc pos; + "ba32 -" >:: ba `ppc neg; + "bl32 +" >:: bl `ppc pos; + "bl32 -" >:: bl `ppc neg; + "bla32 +" >:: bla `ppc pos; + "bla32 -" >:: bla `ppc neg; + + "bc32 counter_unchanged " >:: bc `ppc pos counter_unchanged; + "bc32 counter_decremented" >:: bc `ppc pos counter_decremented; + "bc32 jmp_anyway +" >:: bc `ppc pos jmp_anyway; + "bc32 jmp_anyway -" >:: bc `ppc neg jmp_anyway; + "bc32 cond_ctr_ok_1 +" >:: bc `ppc pos cond_ctr_ok_1; + "bc32 cond_ctr_ok_1 -" >:: bc `ppc neg cond_ctr_ok_1; + "bc32 cond_ctr_ok_2 +" >:: bc `ppc pos cond_ctr_ok_2; + "bc32 cond_ctr_ok_2 -" >:: bc `ppc neg cond_ctr_ok_2; + "bc32 cond_ctr_ok_3 +" >:: bc `ppc pos cond_ctr_ok_3; + "bc32 cond_ctr_ok_3 -" >:: bc `ppc neg cond_ctr_ok_3; + "bc32 cond_ctr_ok_4 +" >:: bc `ppc pos cond_ctr_ok_4; + "bc32 cond_ctr_ok_4 -" >:: bc `ppc neg cond_ctr_ok_4; + "bc32 cond_ok_ctr_not_1 +" >:: bc `ppc pos cond_ok_ctr_not_1; + "bc32 cond_ok_ctr_not_1 -" >:: bc `ppc neg cond_ok_ctr_not_1; + "bc32 cond_not_ctr_ok_1 +" >:: bc `ppc pos cond_not_ctr_ok_1; + "bc32 cond_not_ctr_ok_1 -" >:: bc `ppc neg cond_not_ctr_ok_1; + + "bca32 counter_unchanged " >:: bca `ppc pos counter_unchanged; + "bca32 counter_decremented" >:: bca `ppc pos counter_decremented; + "bca32 jmp_anyway +" >:: bca `ppc pos jmp_anyway; + "bca32 jmp_anyway -" >:: bca `ppc neg jmp_anyway; + "bca32 cond_ctr_ok_1 +" >:: bca `ppc pos cond_ctr_ok_1; + "bca32 cond_ctr_ok_1 -" >:: bca `ppc neg cond_ctr_ok_1; + "bca32 cond_ctr_ok_2 +" >:: bca `ppc pos cond_ctr_ok_2; + "bca32 cond_ctr_ok_2 -" >:: bca `ppc neg cond_ctr_ok_2; + "bca32 cond_ctr_ok_3 +" >:: bca `ppc pos cond_ctr_ok_3; + "bca32 cond_ctr_ok_3 -" >:: bca `ppc neg cond_ctr_ok_3; + "bca32 cond_ctr_ok_4 +" >:: bca `ppc pos cond_ctr_ok_4; + "bca32 cond_ctr_ok_4 -" >:: bca `ppc neg cond_ctr_ok_4; + "bca32 cond_ok_ctr_not_1 +" >:: bca `ppc pos cond_ok_ctr_not_1; + "bca32 cond_ok_ctr_not_1 -" >:: bca `ppc neg cond_ok_ctr_not_1; + "bca32 cond_not_ctr_ok_1 +" >:: bca `ppc pos cond_not_ctr_ok_1; + "bca32 cond_not_ctr_ok_1 -" >:: bca `ppc neg cond_not_ctr_ok_1; + + "bcl32 counter_unchanged " >:: bcl `ppc pos counter_unchanged; + "bcl32 counter_decremented" >:: bcl `ppc pos counter_decremented; + "bcl32 jmp_anyway +" >:: bcl `ppc pos jmp_anyway; + "bcl32 jmp_anyway -" >:: bcl `ppc neg jmp_anyway; + "bcl32 cond_ctr_ok_1 +" >:: bcl `ppc pos cond_ctr_ok_1; + "bcl32 cond_ctr_ok_1 -" >:: bcl `ppc neg cond_ctr_ok_1; + "bcl32 cond_ctr_ok_2 +" >:: bcl `ppc pos cond_ctr_ok_2; + "bcl32 cond_ctr_ok_2 -" >:: bcl `ppc neg cond_ctr_ok_2; + "bcl32 cond_ctr_ok_3 +" >:: bcl `ppc pos cond_ctr_ok_3; + "bcl32 cond_ctr_ok_3 -" >:: bcl `ppc neg cond_ctr_ok_3; + "bcl32 cond_ctr_ok_4 +" >:: bcl `ppc pos cond_ctr_ok_4; + "bcl32 cond_ctr_ok_4 -" >:: bcl `ppc neg cond_ctr_ok_4; + "bcl32 cond_ok_ctr_not_1 +" >:: bcl `ppc pos cond_ok_ctr_not_1; + "bcl32 cond_ok_ctr_not_1 -" >:: bcl `ppc neg cond_ok_ctr_not_1; + "bcl32 cond_not_ctr_ok_1 +" >:: bcl `ppc pos cond_not_ctr_ok_1; + "bcl32 cond_not_ctr_ok_1 -" >:: bcl `ppc neg cond_not_ctr_ok_1; + + "bcla32 counter_unchanged " >:: bcla `ppc pos counter_unchanged; + "bcla32 counter_decremented" >:: bcla `ppc pos counter_decremented; + "bcla32 jmp_anyway +" >:: bcla `ppc pos jmp_anyway; + "bcla32 jmp_anyway -" >:: bcla `ppc neg jmp_anyway; + "bcla32 cond_ctr_ok_1 +" >:: bcla `ppc pos cond_ctr_ok_1; + "bcla32 cond_ctr_ok_1 -" >:: bcla `ppc neg cond_ctr_ok_1; + "bcla32 cond_ctr_ok_2 +" >:: bcla `ppc pos cond_ctr_ok_2; + "bcla32 cond_ctr_ok_2 -" >:: bcla `ppc neg cond_ctr_ok_2; + "bcla32 cond_ctr_ok_3 +" >:: bcla `ppc pos cond_ctr_ok_3; + "bcla32 cond_ctr_ok_3 -" >:: bcla `ppc neg cond_ctr_ok_3; + "bcla32 cond_ctr_ok_4 +" >:: bcla `ppc pos cond_ctr_ok_4; + "bcla32 cond_ctr_ok_4 -" >:: bcla `ppc neg cond_ctr_ok_4; + "bcla32 cond_ok_ctr_not_1 +" >:: bcla `ppc pos cond_ok_ctr_not_1; + "bcla32 cond_ok_ctr_not_1 -" >:: bcla `ppc neg cond_ok_ctr_not_1; + "bcla32 cond_not_ctr_ok_1 +" >:: bcla `ppc pos cond_not_ctr_ok_1; + "bcla32 cond_not_ctr_ok_1 -" >:: bcla `ppc neg cond_not_ctr_ok_1; + + "bclr32 counter_unchanged " >:: bclr `ppc counter_unchanged; + "bclr32 counter_decremented" >:: bclr `ppc counter_decremented; + "bclr32 jmp_anyway" >:: bclr `ppc jmp_anyway; + "bclr32 cond_ctr_ok_1" >:: bclr `ppc cond_ctr_ok_1; + "bclr32 cond_ctr_ok_2" >:: bclr `ppc cond_ctr_ok_2; + "bclr32 cond_ctr_ok_3" >:: bclr `ppc cond_ctr_ok_3; + "bclr32 cond_ctr_ok_4" >:: bclr `ppc cond_ctr_ok_4; + "bclr32 cond_ok_ctr_not_1" >:: bclr `ppc cond_ok_ctr_not_1; + "bclr32 cond_not_ctr_ok_1" >:: bclr `ppc cond_not_ctr_ok_1; + + "bclrl32 counter_unchanged " >:: bclrl `ppc counter_unchanged; + "bclrl32 counter_decremented" >:: bclrl `ppc counter_decremented; + "bclrl32 jmp_anyway" >:: bclrl `ppc jmp_anyway; + "bclrl32 cond_ctr_ok_1" >:: bclrl `ppc cond_ctr_ok_1; + "bclrl32 cond_ctr_ok_2" >:: bclrl `ppc cond_ctr_ok_2; + "bclrl32 cond_ctr_ok_3" >:: bclrl `ppc cond_ctr_ok_3; + "bclrl32 cond_ctr_ok_4" >:: bclrl `ppc cond_ctr_ok_4; + "bclrl32 cond_ok_ctr_not_1" >:: bclrl `ppc cond_ok_ctr_not_1; + "bclrl32 cond_not_ctr_ok_1" >:: bclrl `ppc cond_not_ctr_ok_1; + + "bdnz32 jmp" >:: bdnz ~jmp:true `ppc; + "bdnz32 no jmp" >:: bdnz ~jmp:false `ppc; + "bdnzlr32 jmp" >:: bdnzlr ~jmp:true `ppc; + "bdnzlr32 no jmp" >:: bdnzlr ~jmp:false `ppc; + + "bcctr32 jmp_anyway" >:: bcctr `ppc jmp_anyway; + "bcctr32 cond_ok" >:: bcctr `ppc cond_ok; + "bcctr32 cond_not" >:: bcctr `ppc cond_not; + + "bcctrl32 jmp_anyway" >:: bcctrl `ppc jmp_anyway; + "bcctrl32 cond_ok" >:: bcctrl `ppc cond_ok; + "bcctrl32 cond_not" >:: bcctrl `ppc cond_not; + + + "b64 +" >:: b `ppc64 pos; + "b64 -" >:: b `ppc64 neg; + "ba64 +" >:: ba `ppc64 pos; + "ba64 -" >:: ba `ppc64 neg; + "bl64 +" >:: bl `ppc64 pos; + "bl64 -" >:: bl `ppc64 neg; + "bla64 +" >:: bla `ppc64 pos; + "bla64 -" >:: bla `ppc64 neg; + + "bc64 counter_unchanged " >:: bc `ppc64 pos counter_unchanged; + "bc64 counter_decremented" >:: bc `ppc64 pos counter_decremented; + "bc64 jmp_anyway +" >:: bc `ppc64 pos jmp_anyway; + "bc64 jmp_anyway -" >:: bc `ppc64 neg jmp_anyway; + "bc64 cond_ctr_ok_1 +" >:: bc `ppc64 pos cond_ctr_ok_1; + "bc64 cond_ctr_ok_1 -" >:: bc `ppc64 neg cond_ctr_ok_1; + "bc64 cond_ctr_ok_2 +" >:: bc `ppc64 pos cond_ctr_ok_2; + "bc64 cond_ctr_ok_2 -" >:: bc `ppc64 neg cond_ctr_ok_2; + "bc64 cond_ctr_ok_3 +" >:: bc `ppc64 pos cond_ctr_ok_3; + "bc64 cond_ctr_ok_3 -" >:: bc `ppc64 neg cond_ctr_ok_3; + "bc64 cond_ctr_ok_4 +" >:: bc `ppc64 pos cond_ctr_ok_4; + "bc64 cond_ctr_ok_4 -" >:: bc `ppc64 neg cond_ctr_ok_4; + "bc64 cond_ok_ctr_not_1 +" >:: bc `ppc64 pos cond_ok_ctr_not_1; + "bc64 cond_ok_ctr_not_1 -" >:: bc `ppc64 neg cond_ok_ctr_not_1; + "bc64 cond_not_ctr_ok_1 +" >:: bc `ppc64 pos cond_not_ctr_ok_1; + "bc64 cond_not_ctr_ok_1 -" >:: bc `ppc64 neg cond_not_ctr_ok_1; + + "bca64 counter_unchanged " >:: bca `ppc64 pos counter_unchanged; + "bca64 counter_decremented" >:: bca `ppc64 pos counter_decremented; + "bca64 jmp_anyway +" >:: bca `ppc64 pos jmp_anyway; + "bca64 jmp_anyway -" >:: bca `ppc64 neg jmp_anyway; + "bca64 cond_ctr_ok_1 +" >:: bca `ppc64 pos cond_ctr_ok_1; + "bca64 cond_ctr_ok_1 -" >:: bca `ppc64 neg cond_ctr_ok_1; + "bca64 cond_ctr_ok_2 +" >:: bca `ppc64 pos cond_ctr_ok_2; + "bca64 cond_ctr_ok_2 -" >:: bca `ppc64 neg cond_ctr_ok_2; + "bca64 cond_ctr_ok_3 +" >:: bca `ppc64 pos cond_ctr_ok_3; + "bca64 cond_ctr_ok_3 -" >:: bca `ppc64 neg cond_ctr_ok_3; + "bca64 cond_ctr_ok_4 +" >:: bca `ppc64 pos cond_ctr_ok_4; + "bca64 cond_ctr_ok_4 -" >:: bca `ppc64 neg cond_ctr_ok_4; + "bca64 cond_ok_ctr_not_1 +" >:: bca `ppc64 pos cond_ok_ctr_not_1; + "bca64 cond_ok_ctr_not_1 -" >:: bca `ppc64 neg cond_ok_ctr_not_1; + "bca64 cond_not_ctr_ok_1 +" >:: bca `ppc64 pos cond_not_ctr_ok_1; + "bca64 cond_not_ctr_ok_1 -" >:: bca `ppc64 neg cond_not_ctr_ok_1; + + "bcl64 counter_unchanged " >:: bcl `ppc64 pos counter_unchanged; + "bcl64 counter_decremented" >:: bcl `ppc64 pos counter_decremented; + "bcl64 jmp_anyway +" >:: bcl `ppc64 pos jmp_anyway; + "bcl64 jmp_anyway -" >:: bcl `ppc64 neg jmp_anyway; + "bcl64 cond_ctr_ok_1 +" >:: bcl `ppc64 pos cond_ctr_ok_1; + "bcl64 cond_ctr_ok_1 -" >:: bcl `ppc64 neg cond_ctr_ok_1; + "bcl64 cond_ctr_ok_2 +" >:: bcl `ppc64 pos cond_ctr_ok_2; + "bcl64 cond_ctr_ok_2 -" >:: bcl `ppc64 neg cond_ctr_ok_2; + "bcl64 cond_ctr_ok_3 +" >:: bcl `ppc64 pos cond_ctr_ok_3; + "bcl64 cond_ctr_ok_3 -" >:: bcl `ppc64 neg cond_ctr_ok_3; + "bcl64 cond_ctr_ok_4 +" >:: bcl `ppc64 pos cond_ctr_ok_4; + "bcl64 cond_ctr_ok_4 -" >:: bcl `ppc64 neg cond_ctr_ok_4; + "bcl64 cond_ok_ctr_not_1 +" >:: bcl `ppc64 pos cond_ok_ctr_not_1; + "bcl64 cond_ok_ctr_not_1 -" >:: bcl `ppc64 neg cond_ok_ctr_not_1; + "bcl64 cond_not_ctr_ok_1 +" >:: bcl `ppc64 pos cond_not_ctr_ok_1; + "bcl64 cond_not_ctr_ok_1 -" >:: bcl `ppc64 neg cond_not_ctr_ok_1; + + "bcla64 counter_unchanged " >:: bcla `ppc64 pos counter_unchanged; + "bcla64 counter_decremented" >:: bcla `ppc64 pos counter_decremented; + "bcla64 jmp_anyway +" >:: bcla `ppc64 pos jmp_anyway; + "bcla64 jmp_anyway -" >:: bcla `ppc64 neg jmp_anyway; + "bcla64 cond_ctr_ok_1 +" >:: bcla `ppc64 pos cond_ctr_ok_1; + "bcla64 cond_ctr_ok_1 -" >:: bcla `ppc64 neg cond_ctr_ok_1; + "bcla64 cond_ctr_ok_2 +" >:: bcla `ppc64 pos cond_ctr_ok_2; + "bcla64 cond_ctr_ok_2 -" >:: bcla `ppc64 neg cond_ctr_ok_2; + "bcla64 cond_ctr_ok_3 +" >:: bcla `ppc64 pos cond_ctr_ok_3; + "bcla64 cond_ctr_ok_3 -" >:: bcla `ppc64 neg cond_ctr_ok_3; + "bcla64 cond_ctr_ok_4 +" >:: bcla `ppc64 pos cond_ctr_ok_4; + "bcla64 cond_ctr_ok_4 -" >:: bcla `ppc64 neg cond_ctr_ok_4; + "bcla64 cond_ok_ctr_not_1 +" >:: bcla `ppc64 pos cond_ok_ctr_not_1; + "bcla64 cond_ok_ctr_not_1 -" >:: bcla `ppc64 neg cond_ok_ctr_not_1; + "bcla64 cond_not_ctr_ok_1 +" >:: bcla `ppc64 pos cond_not_ctr_ok_1; + "bcla64 cond_not_ctr_ok_1 -" >:: bcla `ppc64 neg cond_not_ctr_ok_1; + + "bclr64 counter_unchanged " >:: bclr `ppc64 counter_unchanged; + "bclr64 counter_decremented" >:: bclr `ppc64 counter_decremented; + "bclr64 jmp_anyway" >:: bclr `ppc64 jmp_anyway; + "bclr64 cond_ctr_ok_1" >:: bclr `ppc64 cond_ctr_ok_1; + "bclr64 cond_ctr_ok_2" >:: bclr `ppc64 cond_ctr_ok_2; + "bclr64 cond_ctr_ok_3" >:: bclr `ppc64 cond_ctr_ok_3; + "bclr64 cond_ctr_ok_4" >:: bclr `ppc64 cond_ctr_ok_4; + "bclr64 cond_ok_ctr_not_1" >:: bclr `ppc64 cond_ok_ctr_not_1; + "bclr64 cond_not_ctr_ok_1" >:: bclr `ppc64 cond_not_ctr_ok_1; + + "bclrl64 counter_unchanged " >:: bclrl `ppc64 counter_unchanged; + "bclrl64 counter_decremented" >:: bclrl `ppc64 counter_decremented; + "bclrl64 jmp_anyway" >:: bclrl `ppc64 jmp_anyway; + "bclrl64 cond_ctr_ok_1" >:: bclrl `ppc64 cond_ctr_ok_1; + "bclrl64 cond_ctr_ok_2" >:: bclrl `ppc64 cond_ctr_ok_2; + "bclrl64 cond_ctr_ok_3" >:: bclrl `ppc64 cond_ctr_ok_3; + "bclrl64 cond_ctr_ok_4" >:: bclrl `ppc64 cond_ctr_ok_4; + "bclrl64 cond_ok_ctr_not_1" >:: bclrl `ppc64 cond_ok_ctr_not_1; + "bclrl64 cond_not_ctr_ok_1" >:: bclrl `ppc64 cond_not_ctr_ok_1; + + "bdnz64 jmp" >:: bdnz ~jmp:true `ppc64; + "bdnz64 no jmp" >:: bdnz ~jmp:false `ppc64; + "bdnzlr64 jmp" >:: bdnzlr ~jmp:true `ppc64; + "bdnzlr64 no jmp" >:: bdnzlr ~jmp:false `ppc64; + + "bcctr64 jmp_anyway" >:: bcctr `ppc64 jmp_anyway; + "bcctr64 cond_ok" >:: bcctr `ppc64 cond_ok; + "bcctr64 cond_not" >:: bcctr `ppc64 cond_not; + + "bcctrl64 jmp_anyway" >:: bcctrl `ppc64 jmp_anyway; + "bcctrl64 cond_ok" >:: bcctrl `ppc64 cond_ok; + "bcctrl64 cond_not" >:: bcctrl `ppc64 cond_not; + + + ] diff --git a/lib_test/powerpc/powerpc_compare_tests.ml b/lib_test/powerpc/powerpc_compare_tests.ml new file mode 100644 index 000000000..bf2d38cfd --- /dev/null +++ b/lib_test/powerpc/powerpc_compare_tests.ml @@ -0,0 +1,189 @@ +open Core_kernel.Std +open Bap.Std +open OUnit2 + +open Powerpc_tests_helpers + +type expected = LT | GT | EQ + +let cr_field_num = 7 (** in IBM style, i.e. least significant byte *) + +let print_bits lt gt eq = + let str = function + | None -> "unknown" + | Some x -> Word.to_string x in + printf "lt %s; gt %s; eq %s; \n" (str lt) (str gt) (str eq) + +let check ctxt expected = + let cr_lt = cr_bit 28 in + let cr_gt = cr_bit 29 in + let cr_eq = cr_bit 30 in + let lt = lookup_var ctxt cr_lt in + let gt = lookup_var ctxt cr_gt in + let eq = lookup_var ctxt cr_eq in + match expected with + | LT -> + is_equal_words Word.b1 lt && + is_equal_words Word.b0 gt && + is_equal_words Word.b0 eq + | GT -> + is_equal_words Word.b0 lt && + is_equal_words Word.b1 gt && + is_equal_words Word.b0 eq + | EQ -> + is_equal_words Word.b0 lt && + is_equal_words Word.b0 gt && + is_equal_words Word.b1 eq + +let cmpi name ~opcode l_field arch reg_value value expected (_ctxt : test_ctxt) = + let reg_num = 6 in + let opcode = Word.of_int ~width:6 opcode in + let cr_field = Word.of_int ~width:3 cr_field_num in + let l_field = Word.of_int ~width:1 l_field in + let reg = Word.of_int ~width:5 reg_num in + let value = Word.of_int64 ~width:16 value in + let bytes = + make_bytes [opcode; cr_field; Word.b0; l_field; reg; value] in + let reg = find_gpr arch (sprintf "R%d" reg_num) in + let width = arch_width arch in + let init = Bil.[reg := int @@ Word.of_int64 ~width reg_value] in + let c = eval init bytes arch in + assert_bool (sprintf "%s failed" name) @@ check c expected + +let cmpwi = cmpi "cmpwi" ~opcode:11 0 +let cmplwi = cmpi "cmplwi" ~opcode:10 0 +let cmpdi = cmpi "cmpdi" ~opcode:11 1 `ppc64 +let cmpldi = cmpi "cmpldi" ~opcode:10 1 `ppc64 + +let cmp name ~opt_opcode l_field arch reg1_value reg2_value expected (_ctxt : test_ctxt) = + let reg1_num = 6 in + let reg2_num = 7 in + let opcode = Word.of_int ~width:6 31 in + let cr_field = Word.of_int ~width:3 cr_field_num in + let l_field = Word.of_int ~width:1 l_field in + let reg1 = Word.of_int ~width:5 reg1_num in + let reg2 = Word.of_int ~width:5 reg2_num in + let opt_opcode = Word.of_int ~width:10 opt_opcode in + let fin = Word.b0 in + let bytes = + make_bytes [opcode; cr_field; Word.b0; l_field; reg1; reg2; opt_opcode; fin] in + let reg1 = find_gpr arch (sprintf "R%d" reg1_num) in + let reg2 = find_gpr arch (sprintf "R%d" reg2_num) in + let width = arch_width arch in + let init = Bil.[ + reg1 := int @@ Word.of_int64 ~width reg1_value; + reg2 := int @@ Word.of_int64 ~width reg2_value; + ] in + let c = eval init bytes arch in + assert_bool (sprintf "%s failed" name) @@ check c expected + +let cmpw = cmp "cmpw" ~opt_opcode:0 0 +let cmplw = cmp "cmplw" ~opt_opcode:32 0 +let cmpd = cmp "cmpd" ~opt_opcode:0 1 `ppc64 +let cmpld = cmp "cmpld" ~opt_opcode:32 1 `ppc64 + +let suite = "compare" >::: [ + + "cmpwi32: lt" >:: cmpwi `ppc 42L 44L LT; + "cmpwi32: gt" >:: cmpwi `ppc 44L 42L GT; + "cmpwi32: eq" >:: cmpwi `ppc 42L 42L EQ; + "cmpwi32: 32lt" >:: cmpwi `ppc 0x0BCDEFAB_00000042L 0x44L LT; + "cmpwi32: lt signed" >:: cmpwi `ppc (-42L) (-41L) LT; + "cmpwi32: gt signed" >:: cmpwi `ppc 44L (-42L) GT; + "cmpwi32: eq signed" >:: cmpwi `ppc (-42L) (-42L) EQ; + + "cmpw32: lt" >:: cmpw `ppc 42L 44L LT; + "cmpw32: gt" >:: cmpw `ppc 44L 42L GT; + "cmpw32: eq" >:: cmpw `ppc 42L 42L EQ; + "cmpw32: 32lt" >:: cmpw `ppc 0x0BCDEFAB_00000042L 0x44L LT; + "cmpw32: lt signed" >:: cmpw `ppc (-42L) (-41L) LT; + "cmpw32: gt signed" >:: cmpw `ppc 44L (-42L) GT; + "cmpw32: eq signed" >:: cmpw `ppc (-42L) (-42L) EQ; + + "cmpw32: lt" >:: cmpw `ppc 42L 44L LT; + "cmpw32: gt" >:: cmpw `ppc 44L 42L GT; + "cmpw32: eq" >:: cmpw `ppc 42L 42L EQ; + "cmpw32: 32lt" >:: cmpw `ppc 0x0BCDEFAB_00000042L 0x44L LT; + "cmpw32: lt signed" >:: cmpw `ppc (-42L) (-41L) LT; + "cmpw32: gt signed" >:: cmpw `ppc 44L (-42L) GT; + "cmpw32: eq signed" >:: cmpw `ppc (-42L) (-42L) EQ; + + "cmplwi32: lt" >:: cmplwi `ppc 42L 44L LT; + "cmplwi32: gt" >:: cmplwi `ppc 44L 42L GT; + "cmplwi32: eq" >:: cmplwi `ppc 42L 42L EQ; + "cmplwi32: 32lt" >:: cmplwi `ppc 0x0BCDEFAB_00000042L 0x44L LT; + "cmplwi32: lt big" >:: cmplwi `ppc 42L 0xFFFFFFFFL LT; + "cmplwi32: gt big" >:: cmplwi `ppc 0xFFFFFFFF_FFFFFFFFL 42L GT; + + "cmplw32: lt" >:: cmplw `ppc 42L 44L LT; + "cmplw32: gt" >:: cmplw `ppc 44L 42L GT; + "cmplw32: eq" >:: cmplw `ppc 42L 42L EQ; + "cmplw32: 32lt" >:: cmplw `ppc 0x0BCDEFAB_00000042L 0x44L LT; + "cmplw32: lt big" >:: cmplw `ppc 42L 0xFFFFFFFFL LT; + "cmplw32: gt big" >:: cmplw `ppc 0xFFFFFFFF_FFFFFFFFL 42L GT; + + "cmpwi64: lt" >:: cmpwi `ppc64 42L 44L LT; + "cmpwi64: gt" >:: cmpwi `ppc64 44L 42L GT; + "cmpwi64: eq" >:: cmpwi `ppc64 42L 42L EQ; + "cmpwi64: 64lt" >:: cmpwi `ppc64 0x0BCDEFAB_00000042L 0x44L LT; + "cmpwi64: lt signed" >:: cmpwi `ppc64 (-42L) (-41L) LT; + "cmpwi64: gt signed" >:: cmpwi `ppc64 44L (-42L) GT; + "cmpwi64: eq signed" >:: cmpwi `ppc64 (-42L) (-42L) EQ; + + "cmpw64: lt" >:: cmpw `ppc64 42L 44L LT; + "cmpw64: gt" >:: cmpw `ppc64 44L 42L GT; + "cmpw64: eq" >:: cmpw `ppc64 42L 42L EQ; + "cmpw64: 64lt" >:: cmpw `ppc64 0x0BCDEFAB_00000042L 0x44L LT; + "cmpw64: lt signed" >:: cmpw `ppc64 (-42L) (-41L) LT; + "cmpw64: gt signed" >:: cmpw `ppc64 44L (-42L) GT; + "cmpw64: eq signed" >:: cmpw `ppc64 (-42L) (-42L) EQ; + + "cmplwi64: lt" >:: cmplwi `ppc64 42L 44L LT; + "cmplwi64: gt" >:: cmplwi `ppc64 44L 42L GT; + "cmplwi64: eq" >:: cmplwi `ppc64 42L 42L EQ; + "cmplwi64: 64lt" >:: cmplwi `ppc64 0x0BCDEFAB_00000042L 0x44L LT; + "cmplwi64: lt big" >:: cmplwi `ppc64 42L 0xFFFFFFFFL LT; + "cmplwi64: gt big" >:: cmplwi `ppc64 0xFFFFFFFF_FFFFFFFFL 42L GT; + + "cmplw64: lt" >:: cmplw `ppc64 42L 44L LT; + "cmplw64: gt" >:: cmplw `ppc64 44L 42L GT; + "cmplw64: eq" >:: cmplw `ppc64 42L 42L EQ; + "cmplw64: 64lt" >:: cmplw `ppc64 0x0BCDEFAB_00000042L 0x44L LT; + "cmplw64: lt big" >:: cmplw `ppc64 42L 0xFFFFFFFFL LT; + "cmplw64: gt big" >:: cmplw `ppc64 0xFFFFFFFF_FFFFFFFFL 42L GT; + + "cmpdi: lt" >:: cmpdi 42L 44L LT; + "cmpdi: gt" >:: cmpdi 44L 42L GT; + "cmpdi: eq" >:: cmpdi 42L 42L EQ; + "cmpdi: 64 operand, 1" >:: cmpdi 0x0BCDEFAB_00000042L 0x44L GT; + "cmpdi: 64 operand, 2" >:: cmpdi 0xFBCDEFAB_00000042L 0x44L LT; + "cmpdi: lt signed" >:: cmpdi (-42L) (-41L) LT; + "cmpdi: gt signed" >:: cmpdi 44L (-42L) GT; + "cmpdi: eq signed" >:: cmpdi (-42L) (-42L) EQ; + + "cmpd: lt" >:: cmpd 42L 44L LT; + "cmpd: gt" >:: cmpd 44L 42L GT; + "cmpd: eq" >:: cmpd 42L 42L EQ; + "cmpd: 64 operand, 1" >:: cmpd 0x0BCDEFAB_00000042L 0x44L GT; + "cmpd: 64 operand, 2" >:: cmpd 0xFBCDEFAB_00000042L 0x44L LT; + "cmpd: lt signed" >:: cmpd (-42L) (-41L) LT; + "cmpd: gt signed" >:: cmpd 44L (-42L) GT; + "cmpd: eq signed" >:: cmpd (-42L) (-42L) EQ; + + "cmpldi: lt" >:: cmpldi 42L 44L LT; + "cmpldi: gt" >:: cmpldi 44L 42L GT; + "cmpldi: eq" >:: cmpldi 42L 42L EQ; + "cmpldi: 64 operand, 1" >:: cmpldi 0x0BCDEFAB_00000042L 0x44L GT; + "cmpldi: 64 operand, 2" >:: cmpldi 0xFBCDEFAB_00000042L 0x44L GT; + "cmpldi: lt big" >:: cmpldi 42L 0xFFFFFFFFL LT; + "cmpldi: gt big" >:: cmpldi 0xFFFFFFFF_FFFFFFFFL 42L GT; + + "cmpld: lt" >:: cmpld 42L 44L LT; + "cmpld: gt" >:: cmpld 44L 42L GT; + "cmpld: eq" >:: cmpld 42L 42L EQ; + "cmpld: 64 operand, 1" >:: cmpld 0x0BCDEFAB_00000042L 0x44L GT; + "cmpld: 64 operand, 2" >:: cmpld 0xFBCDEFAB_00000042L 0x44L GT; + "cmpld: lt big" >:: cmpld 42L 0xFFFFFFFFL LT; + "cmpld: gt big" >:: cmpld 0xFFFFFFFF_FFFFFFFFL 42L GT; + + ] diff --git a/lib_test/powerpc/powerpc_cr_tests.ml b/lib_test/powerpc/powerpc_cr_tests.ml new file mode 100644 index 000000000..0096e10a9 --- /dev/null +++ b/lib_test/powerpc/powerpc_cr_tests.ml @@ -0,0 +1,150 @@ +open Core_kernel.Std +open Bap.Std +open OUnit2 + +open Powerpc_tests_helpers + +let crand arch ctxt = + let name = "CRAND" in + let bytes = make_insn ~name `XL [19; 1; 2; 3; 257; 0] in + let cr1 = cr_bit 1 in + let cr2 = cr_bit 2 in + let cr3 = cr_bit 3 in + let init = Bil.[ + cr2 := int Word.b1; + cr3 := int Word.b1; + ] in + check_gpr init bytes cr1 Word.b1 arch ctxt + +let crnand arch ctxt = + let name = "CRNAND" in + let bytes = make_insn ~name `XL [19; 1; 2; 3; 225; 0] in + let cr1 = cr_bit 1 in + let cr2 = cr_bit 2 in + let cr3 = cr_bit 3 in + let init = Bil.[ + cr2 := int Word.b1; + cr3 := int Word.b1; + ] in + check_gpr init bytes cr1 Word.b0 arch ctxt + +let cror arch ctxt = + let name = "CROR" in + let bytes = make_insn ~name `XL [19; 1; 2; 3; 449; 0] in + let cr1 = cr_bit 1 in + let cr2 = cr_bit 2 in + let cr3 = cr_bit 3 in + let init = Bil.[ + cr2 := int Word.b1; + cr3 := int Word.b0; + ] in + check_gpr init bytes cr1 Word.b1 arch ctxt + +let crxor arch ctxt = + let name = "CRXOR" in + let bytes = make_insn ~name `XL [19; 1; 2; 3; 193; 0] in + let cr1 = cr_bit 1 in + let cr2 = cr_bit 2 in + let cr3 = cr_bit 3 in + let init = Bil.[ + cr2 := int Word.b1; + cr3 := int Word.b1; + ] in + check_gpr init bytes cr1 Word.b0 arch ctxt + +let crnor arch ctxt = + let name = "CRNOR" in + let bytes = make_insn ~name `XL [19; 1; 2; 3; 33; 0] in + let cr1 = cr_bit 1 in + let cr2 = cr_bit 2 in + let cr3 = cr_bit 3 in + let init = Bil.[ + cr2 := int Word.b0; + cr3 := int Word.b0; + ] in + check_gpr init bytes cr1 Word.b1 arch ctxt + +let creqv arch ctxt = + let name = "CREQV" in + let bytes = make_insn ~name `XL [19; 1; 2; 3; 289; 0] in + let cr1 = cr_bit 1 in + let cr2 = cr_bit 2 in + let cr3 = cr_bit 3 in + let init = Bil.[ + cr2 := int Word.b1; + cr3 := int Word.b1; + ] in + check_gpr init bytes cr1 Word.b1 arch ctxt + +let crandc arch ctxt = + let name = "CRANDC" in + let bytes = make_insn ~name `XL [19; 1; 2; 3; 129; 0] in + let cr1 = cr_bit 1 in + let cr2 = cr_bit 2 in + let cr3 = cr_bit 3 in + let init = Bil.[ + cr2 := int Word.b1; + cr3 := int Word.b0; + ] in + check_gpr init bytes cr1 Word.b1 arch ctxt + +let crorc arch ctxt = + let name = "CRORC" in + let bytes = make_insn ~name `XL [19; 1; 2; 3; 417; 0] in + let cr1 = cr_bit 1 in + let cr2 = cr_bit 2 in + let cr3 = cr_bit 3 in + let init = Bil.[ + cr2 := int Word.b0; + cr3 := int Word.b0; + ] in + check_gpr init bytes cr1 Word.b1 arch ctxt + +let mcrf arch ctxt = + let name = "MCRF" in + let bytes = make_insn ~name `XL [19; 1; 0; 3; 0; 0; 0; 0] in + let cr4 = cr_bit 4 in + let cr5 = cr_bit 5 in + let cr6 = cr_bit 6 in + let cr7 = cr_bit 7 in + let cr12 = cr_bit 12 in + let cr13 = cr_bit 13 in + let cr14 = cr_bit 14 in + let cr15 = cr_bit 15 in + let init = Bil.[ + cr12 := int Word.b1; + cr13 := int Word.b0; + cr14 := int Word.b1; + cr15 := int Word.b0; + ] in + let ctxt = eval init bytes arch in + let cr4_val = lookup_var ctxt cr4 in + let cr5_val = lookup_var ctxt cr5 in + let cr6_val = lookup_var ctxt cr6 in + let cr7_val = lookup_var ctxt cr7 in + assert_bool "mcrf failed: bit 4" (is_equal_words Word.b1 cr4_val); + assert_bool "mcrf failed: bit 5" (is_equal_words Word.b0 cr5_val); + assert_bool "mcrf failed: bit 6" (is_equal_words Word.b1 cr6_val); + assert_bool "mcrf failed: bit 7" (is_equal_words Word.b0 cr7_val) + +let suite = "CR" >::: [ + "crand" >:: crand `ppc; + "crnand" >:: crnand `ppc; + "cror" >:: cror `ppc; + "crxor" >:: crxor `ppc; + "crnor" >:: crnor `ppc; + "creqv" >:: creqv `ppc; + "crandc" >:: crandc `ppc; + "crorc" >:: crorc `ppc; + "mcrf" >:: mcrf `ppc; + + "crand 64" >:: crand `ppc64; + "crnand 64" >:: crnand `ppc64; + "cror 64" >:: cror `ppc64; + "crxor 64" >:: crxor `ppc64; + "crnor 64" >:: crnor `ppc64; + "creqv 64" >:: creqv `ppc64; + "crandc 64" >:: crandc `ppc64; + "crorc 64" >:: crorc `ppc64; + "mcrf 64" >:: mcrf `ppc64; + ] diff --git a/lib_test/powerpc/powerpc_load_tests.ml b/lib_test/powerpc/powerpc_load_tests.ml new file mode 100644 index 000000000..07328fb22 --- /dev/null +++ b/lib_test/powerpc/powerpc_load_tests.ml @@ -0,0 +1,477 @@ +open Core_kernel.Std +open Bap.Std +open OUnit2 + +open Powerpc_tests_helpers + +let endian = BigEndian + +let env_of_arch arch = + mem arch, Size.in_bits (Arch.addr_size arch) + +let lz name opcode size arch ~d_addr ~value ctxt = + let bytes = make_insn ~name `D [opcode; 9; 28; d_addr] in + let mem, width = env_of_arch arch in + let r9 = find_gpr arch "R9" in + let r28 = find_gpr arch "R28" in + let addr = 0xABCDEF00 in + let ea = Word.of_int ~width (addr + d_addr) in + let data = Word.of_int ~width:32 value in + let init = Bil.[ + mem := store ~mem:(var mem) ~addr:(int ea) (int data) endian size; + r28 := int (Word.of_int ~width addr); + r9 := int (Word.of_int64 ~width 0xFFFFFFFFFFFFFFFFL); + ] in + let expected = Word.of_int ~width value in + check_gpr init bytes r9 expected arch ctxt + +let lbz = lz "LBZ" 34 `r8 +let lhz = lz "LHZ" 40 `r16 +let lwz = lz "LWZ" 32 `r32 + +let lz_zero_reg name opcode size arch ~d_addr ~value ctxt = + let bytes = make_insn ~name `D [opcode; 9; 0; d_addr] in + let mem, width = env_of_arch arch in + let r9 = find_gpr arch "R9" in + let ea = Word.of_int ~width d_addr in + let data = Word.of_int ~width:32 value in + let init = Bil.[ + mem := store ~mem:(var mem) ~addr:(int ea) (int data) endian size; + r9 := int (Word.of_int64 ~width 0xFFFFFFFFFFFFFFFFL); + ] in + let expected = Word.of_int ~width value in + check_gpr init bytes r9 expected arch ctxt + +let lbz_zero_reg = lz_zero_reg "LBZ" 34 `r8 +let lhz_zero_reg = lz_zero_reg "LHZ" 40 `r16 +let lwz_zero_reg = lz_zero_reg "LWZ" 32 `r32 + +let lzx name opt size arch ~value ctxt = + let bytes = make_insn ~name `X [31; 9; 10; 29; opt] in + let mem, width = env_of_arch arch in + let r9 = find_gpr arch "R9" in + let r10 = find_gpr arch "R10" in + let r29 = find_gpr arch "R29" in + let x = 0xABCD0000 in + let y = 0x0000FF42 in + let ea = Word.of_int ~width (x + y) in + let data = Word.of_int ~width:32 value in + let init = Bil.[ + mem := store ~mem:(var mem) ~addr:(int ea) (int data) endian size; + r29 := int @@ Word.of_int ~width x; + r10 := int @@ Word.of_int ~width y; + r9 := int (Word.of_int64 ~width 0xFFFFFFFFFFFFFFFFL); + ] in + let expected = Word.of_int ~width value in + check_gpr init bytes r9 expected arch ctxt + +let lbzx = lzx "LBZX" 87 `r8 +let lhzx = lzx "LHZX" 279 `r16 +let lwzx = lzx "LWZX" 23 `r32 + +let lzx_zero_reg name opt size arch ~value ctxt = + let bytes = make_insn ~name `X [31; 9; 0; 10; opt] in + let mem, width = env_of_arch arch in + let r9 = find_gpr arch "R9" in + let r10 = find_gpr arch "R10" in + let addr = 0xABCD0000 in + let ea = Word.of_int ~width addr in + let data = Word.of_int ~width:32 value in + let init = Bil.[ + mem := store ~mem:(var mem) ~addr:(int ea) (int data) endian size; + r10 := int @@ Word.of_int ~width addr; + r9 := int (Word.of_int64 ~width 0xFFFFFFFFFFFFFFFFL); + ] in + let expected = Word.of_int ~width value in + check_gpr init bytes r9 expected arch ctxt + +let lbzx_zero_reg = lzx_zero_reg "LBZX" 87 `r8 +let lhzx_zero_reg = lzx_zero_reg "LHZX" 279 `r16 +let lwzx_zero_reg = lzx_zero_reg "LWZX" 23 `r32 + +let lzu name opcode size arch ~d_addr ~value ctxt = + let bytes = make_insn ~name `D [opcode; 9; 28; d_addr] in + let mem, width = env_of_arch arch in + let r9 = find_gpr arch "R9" in + let r28 = find_gpr arch "R28" in + let addr = 0xABCDEF04 in + let ea = Word.of_int ~width (addr + d_addr) in + let data = Word.of_int ~width:32 value in + let init = Bil.[ + mem := store ~mem:(var mem) ~addr:(int ea) (int data) endian size; + r28 := int (Word.of_int ~width addr); + r9 := int (Word.of_int64 ~width 0xFFFFFFFFFFFFFFFFL); + ] in + let expected = Word.of_int ~width value in + check_gpr init bytes r9 expected arch ctxt; + let expected_addr = Word.of_int ~width (addr + d_addr) in + check_gpr init bytes r28 expected_addr arch ctxt + +let lbzu = lzu "LBZU" 35 `r8 +let lhzu = lzu "LHZU" 41 `r16 +let lwzu = lzu "LWZU" 33 `r32 + +let lzux name opt_opcode size arch ~value ctxt = + let bytes = make_insn ~name `X [31; 9; 29; 10; opt_opcode] in + let mem, width = env_of_arch arch in + let r9 = find_gpr arch "R9" in + let r10 = find_gpr arch "R10" in + let r29 = find_gpr arch "R29" in + let x = 0xABCD0000 in + let y = 0x0000EF42 in + let ea = Word.of_int ~width (x + y) in + let x = Word.of_int ~width x in + let y = Word.of_int ~width y in + let data = Word.of_int ~width:32 value in + let init = Bil.[ + mem := store ~mem:(var mem) ~addr:(int ea) (int data) endian size; + r29 := int x; + r10 := int y; + r9 := int (Word.of_int64 ~width 0xFFFFFFFFFFFFFFFFL); + ] in + let expected = Word.of_int ~width value in + check_gpr init bytes r9 expected arch ctxt; + let expected_addr = Word.of_int ~width 0xABCDEF42 in + check_gpr init bytes r29 expected_addr arch ctxt + +let lbzux = lzux "LBZUX" 119 `r8 +let lhzux = lzux "LHZUX" 311 `r16 +let lwzux = lzux "LWZUX" 55 `r32 + +let lha arch ctxt = + let bytes = "\xa8\x29\x00\x05" in (** lha r1, 5(r9) *) + let r1 = find_gpr arch "R1" in + let r9 = find_gpr arch "R9" in + let mem, width = env_of_arch arch in + let addr = 0x00ABCDEF in + let ea = Word.of_int ~width (addr + 5) in + let data = Word.of_int ~width 0xffab in + let init = Bil.[ + mem := store ~mem:(var mem) ~addr:(int ea) (int data) endian `r16; + r9 := int (Word.of_int ~width addr); + ] in + let expected = Word.of_int64 ~width 0xffffffff_ffffffabL in + check_gpr init bytes r1 expected arch ctxt + +let lhax arch ctxt = + let bytes = "\x7c\x25\x4a\xae" in (** lhax r1, r5, r9 *) + let r1 = find_gpr arch "R1" in + let r5 = find_gpr arch "R5" in + let r9 = find_gpr arch "R9" in + let mem, width = env_of_arch arch in + let addr = 0x00ABCDEF in + let disp = 5 in + let ea = Word.of_int ~width (addr + disp) in + let data = Word.of_int ~width 0xffab in + let init = Bil.[ + mem := store ~mem:(var mem) ~addr:(int ea) (int data) endian `r16; + r5 := int (Word.of_int ~width disp); + r9 := int (Word.of_int ~width addr); + ] in + let expected = Word.of_int64 ~width 0xffffffff_ffffffabL in + check_gpr init bytes r1 expected arch ctxt + +let lhau arch ctxt = + let bytes = "\xac\x29\x00\x05" in (** lhau r1, 5(r9) *) + let r1 = find_gpr arch "R1" in + let r9 = find_gpr arch "R9" in + let mem, width = env_of_arch arch in + let addr = 0x00ABCDEF in + let ea = Word.of_int ~width (addr + 5) in + let data = Word.of_int ~width 0xffab in + let init = Bil.[ + mem := store ~mem:(var mem) ~addr:(int ea) (int data) endian `r16; + r9 := int (Word.of_int ~width addr); + ] in + let expected = Word.of_int64 ~width 0xffffffff_ffffffabL in + check_gpr init bytes r1 expected arch ctxt; + let expected_addr = Word.of_int ~width (addr + 5) in + check_gpr init bytes r9 expected_addr arch ctxt + +let lhaux arch ctxt = + let bytes = "\x7c\x25\x4a\xee" in (** lhaux r1, r5, r9 *) + let r1 = find_gpr arch "R1" in + let r5 = find_gpr arch "R5" in + let r9 = find_gpr arch "R9" in + let mem, width = env_of_arch arch in + let addr = 0x00ABCDEF in + let disp = 5 in + let ea = Word.of_int ~width (addr + disp) in + let data = Word.of_int ~width 0x0fab in + let init = Bil.[ + mem := store ~mem:(var mem) ~addr:(int ea) (int data) endian `r16; + r5 := int (Word.of_int ~width disp); + r9 := int (Word.of_int ~width addr); + ] in + let expected = Word.of_int64 ~width 0x00000000_000000fabL in + check_gpr init bytes r1 expected arch ctxt; + let expected_addr = Word.of_int ~width (addr + disp) in + check_gpr init bytes r5 expected_addr arch ctxt + +let lwa arch ctxt = + let bytes = "\xeb\xeb\x01\x16" in (** lwa r31, 276(r11) *) + let r31 = find_gpr arch "R31" in + let r11 = find_gpr arch "R11" in + let mem, width = env_of_arch arch in + let addr = 0x00ABCDEF in + let disp = 276 in + let ea = Word.of_int ~width (addr + disp) in + let data = Word.of_int64 ~width 0xffacffabL in + let init = Bil.[ + mem := store ~mem:(var mem) ~addr:(int ea) (int data) endian `r32; + r11 := int (Word.of_int ~width addr); + ] in + let expected = Word.of_int64 ~width 0xffffffff_ffacffabL in + check_gpr init bytes r31 expected arch ctxt + +let lwax arch ctxt = + let bytes = "\x7c\x25\x4a\xaa" in (** lwax r1, r5, r9 *) + let r1 = find_gpr arch "R1" in + let r5 = find_gpr arch "R5" in + let r9 = find_gpr arch "R9" in + let mem, width = env_of_arch arch in + let addr = 0x00ABCDEF in + let disp = 5 in + let ea = Word.of_int ~width (addr + disp) in + let data = Word.of_int64 ~width 0x0facffabL in + let init = Bil.[ + mem := store ~mem:(var mem) ~addr:(int ea) (int data) endian `r32; + r5 := int (Word.of_int ~width disp); + r9 := int (Word.of_int ~width addr); + ] in + let expected = Word.of_int64 ~width 0x00000000_0facffabL in + check_gpr init bytes r1 expected arch ctxt + +let lwaux arch ctxt = + let bytes = "\x7c\x25\x4a\xea" in (** lwaux r1, r5, r9 *) + let r1 = find_gpr arch "R1" in + let r5 = find_gpr arch "R5" in + let r9 = find_gpr arch "R9" in + let mem, width = env_of_arch arch in + let addr = 0x00ABCDEF in + let disp = 5 in + let ea = Word.of_int ~width (addr + disp) in + let data = Word.of_int64 ~width 0xffacffabL in + let init = Bil.[ + mem := store ~mem:(var mem) ~addr:(int ea) (int data) endian `r32; + r5 := int (Word.of_int ~width disp); + r9 := int (Word.of_int ~width addr); + ] in + let expected = Word.of_int64 ~width 0xffffffff_ffacffabL in + check_gpr init bytes r1 expected arch ctxt; + let expected_addr = Word.of_int ~width (addr + disp) in + check_gpr init bytes r5 expected_addr arch ctxt + +let ld ctxt = + let bytes = "\xe8\x29\x00\x08" in (** ld r1, 8(r9) *) + let arch = `ppc64 in + let r1 = find_gpr arch "R1" in + let r9 = find_gpr arch "R9" in + let mem, width = env_of_arch arch in + let addr = 0x00ABCDEF in + let disp = 8 in + let ea = Word.of_int ~width (addr + disp) in + let data = Word.of_int64 0xffacbbdd_ffacffabL in + let init = Bil.[ + mem := store ~mem:(var mem) ~addr:(int ea) (int data) endian `r64; + r9 := int (Word.of_int ~width:64 addr); + ] in + let expected = data in + check_gpr init bytes r1 expected arch ctxt + +let ldx ctxt = + let bytes = "\x7c\x28\x48\x2a" in (** ldx r1, r8, r9 *) + let arch = `ppc64 in + let r1 = find_gpr arch "R1" in + let r8 = find_gpr arch "R8" in + let r9 = find_gpr arch "R9" in + let mem, width = env_of_arch arch in + let addr = 0x00ABCDEF in + let disp = 5 in + let ea = Word.of_int ~width (addr + disp) in + let data = Word.of_int64 0xffacbbdd_ffacffabL in + let init = Bil.[ + mem := store ~mem:(var mem) ~addr:(int ea) (int data) endian `r64; + r9 := int (Word.of_int ~width:64 addr); + r8 := int (Word.of_int ~width:64 disp); + ] in + let expected = data in + check_gpr init bytes r1 expected arch ctxt + +let ldu ctxt = + let bytes = "\xe8\x29\x00\x09" in (** ldu r1, 8(r9) *) + let arch = `ppc64 in + let r1 = find_gpr arch "R1" in + let r9 = find_gpr arch "R9" in + let mem, width = env_of_arch arch in + let addr = 0x00ABCDEF in + let disp = 8 in + let ea = Word.of_int ~width (addr + disp) in + let data = Word.of_int64 0xffacbbdd_ffacffabL in + let init = Bil.[ + mem := store ~mem:(var mem) ~addr:(int ea) (int data) endian `r64; + r9 := int (Word.of_int ~width:64 addr); + ] in + let expected = data in + check_gpr init bytes r1 expected arch ctxt; + let expected_addr = Word.of_int ~width:64 (addr + disp) in + check_gpr init bytes r9 expected_addr arch ctxt + +let ldux ctxt = + let bytes = "\x7c\x28\x48\x6a" in (** ldux r1, r8, r9 *) + let arch = `ppc64 in + let r1 = find_gpr arch "R1" in + let r8 = find_gpr arch "R8" in + let r9 = find_gpr arch "R9" in + let mem, width = env_of_arch arch in + let addr = 0x00ABCDEF in + let disp = 5 in + let ea = Word.of_int ~width (addr + disp) in + let data = Word.of_int64 0xffacbbdd_ffacffabL in + let init = Bil.[ + mem := store ~mem:(var mem) ~addr:(int ea) (int data) endian `r64; + r9 := int (Word.of_int ~width:64 addr); + r8 := int (Word.of_int ~width:64 disp); + ] in + let expected = data in + check_gpr init bytes r1 expected arch ctxt; + let expected_addr = Word.of_int ~width:64 (addr + disp) in + check_gpr init bytes r8 expected_addr arch ctxt + +let ldux_big_addr ctxt = + let bytes = "\x7c\x28\x48\x6a" in (** ldux r1, r8, r9 *) + let arch = `ppc64 in + let r1 = find_gpr arch "R1" in + let r8 = find_gpr arch "R8" in + let r9 = find_gpr arch "R9" in + let mem, _width = env_of_arch arch in + let addr = Word.of_int64 0xCDEF4234_CDABCDEFL in + let disp = Word.of_int64 5L in + let ea = Word.(addr + disp) in + let data = Word.of_int64 0xffacbbdd_ffacffabL in + let init = Bil.[ + mem := store ~mem:(var mem) ~addr:(int ea) (int data) endian `r64; + r9 := int addr; + r8 := int disp; + ] in + let expected = data in + check_gpr init bytes r1 expected arch ctxt; + let expected_addr = ea in + check_gpr init bytes r8 expected_addr arch ctxt + +let lbrx name opt_opcode size arch ctxt = + let bytes = make_insn ~name `X [31; 1; 2; 3; opt_opcode; 0] in + let mem, width = env_of_arch arch in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let addr = 0xABCDEF00 in + let d_addr = 0x42 in + let ea = Word.of_int ~width (addr + d_addr) in + let data = Word.of_int64 0xABCDEFAB_CCDDEEFFL in + let init = Bil.[ + mem := store ~mem:(var mem) ~addr:(int ea) (int data) endian size; + r2 := int (Word.of_int ~width addr); + r3 := int (Word.of_int ~width d_addr); + ] in + let bits = Size.in_bits size in + let data = Word.extract_exn ~hi:(bits - 1) data in + let expected = + Seq.to_list_rev (Word.enum_bytes data endian) |> + List.fold ~init:None ~f:(fun acc b -> + match acc with + | None -> Some b + | Some p -> Some (Word.concat p b)) |> + Option.value_exn in + let expected = Word.extract_exn ~hi:(width -1) expected in + check_gpr init bytes r1 expected arch ctxt + +let lhbrx = lbrx "LHBRX" 790 `r16 +let lwbrx = lbrx "LWBRX" 534 `r32 +let ldbrx = lbrx "LDBRX" 532 `r64 `ppc64 + +let suite = "load" >::: [ + "lbz32 +imm" >:: lbz `ppc ~d_addr:20 ~value:0x42; + "lbz32 -imm" >:: lbz `ppc ~d_addr:(-16) ~value:0x42; + "lbz32 0 reg" >:: lbz_zero_reg `ppc ~d_addr:20 ~value:0x42; + "lhz32 +imm" >:: lhz `ppc ~d_addr:20 ~value:0x4242; + "lhz32 -imm" >:: lhz `ppc ~d_addr:(-16) ~value:0x4252; + "lhz32 0 reg" >:: lhz_zero_reg `ppc ~d_addr:20 ~value:0x4242; + "lwz32 +imm" >:: lwz `ppc ~d_addr:20 ~value:0xAAAA4242; + "lwz32 -imm" >:: lwz `ppc ~d_addr:(-16) ~value:0xAAAA4252; + "lwz32 0 reg" >:: lwz_zero_reg `ppc ~d_addr:20 ~value:0xAAAA4242; + + "lbzx32" >:: lbzx `ppc ~value:0x42; + "lbzx32 0 reg" >:: lbzx_zero_reg `ppc ~value:0x42; + "lhzx32 +imm" >:: lhzx `ppc ~value:0x4242; + "lhzx32 0 reg" >:: lhzx_zero_reg `ppc ~value:0x4242; + "lwzx32 +imm" >:: lwzx `ppc ~value:0xAAAA4242; + "lwzx32 0 reg" >:: lwzx_zero_reg `ppc ~value:0xAAAA4242; + + "lbzu32 +imm" >:: lbzu `ppc ~d_addr:20 ~value:0x42; + "lbzu32 -imm" >:: lbzu `ppc ~d_addr:(-16) ~value:0x42; + "lhzu32 +imm" >:: lhzu `ppc ~d_addr:20 ~value:0x4242; + "lhzu32 -imm" >:: lhzu `ppc ~d_addr:(-16) ~value:0x4252; + "lwzu32 +imm" >:: lwzu `ppc ~d_addr:20 ~value:0xAAAA4242; + "lwzu32 -imm" >:: lwzu `ppc ~d_addr:(-16) ~value:0xAAAA4252; + + "lbzux32" >:: lbzux `ppc ~value:0x42; + "lhzux32" >:: lhzux `ppc ~value:0x4242; + "lwzux32" >:: lwzux `ppc ~value:0xAAAA4242; + + "lha32" >:: lha `ppc; + "lhax32" >:: lhax `ppc; + "lhau32" >:: lhau `ppc; + "lhaux32" >:: lhaux `ppc; + "lwa32" >:: lwa `ppc; + "lwax32" >:: lwax `ppc; + "lwaux32" >:: lwaux `ppc; + + "lhbrx32" >:: lhbrx `ppc; + "lwbrx32" >:: lwbrx `ppc; + + "lbz64 +imm" >:: lbz `ppc64 ~d_addr:20 ~value:0x42; + "lbz64 -imm" >:: lbz `ppc64 ~d_addr:(-16) ~value:0x42; + "lbz64 0 reg" >:: lbz_zero_reg `ppc64 ~d_addr:20 ~value:0x42; + "lhz64 +imm" >:: lhz `ppc64 ~d_addr:20 ~value:0x4242; + "lhz64 -imm" >:: lhz `ppc64 ~d_addr:(-16) ~value:0x4252; + "lhz64 0 reg" >:: lhz_zero_reg `ppc64 ~d_addr:20 ~value:0x4242; + "lwz64 +imm" >:: lwz `ppc64 ~d_addr:20 ~value:0xAAAA4242; + "lwz64 -imm" >:: lwz `ppc64 ~d_addr:(-16) ~value:0xAAAA4252; + "lwz64 0 reg" >:: lwz_zero_reg `ppc64 ~d_addr:20 ~value:0xAAAA4242; + + "lbzx64" >:: lbzx `ppc64 ~value:0x42; + "lbzx64 0 reg" >:: lbzx_zero_reg `ppc64 ~value:0x42; + "lhzx64 +imm" >:: lhzx `ppc64 ~value:0x4242; + "lhzx64 0 reg" >:: lhzx_zero_reg `ppc64 ~value:0x4242; + "lwzx64 +imm" >:: lwzx `ppc64 ~value:0xAAAA4242; + "lwzx64 0 reg" >:: lwzx_zero_reg `ppc64 ~value:0xAAAA4242; + + "lbzu64 +imm" >:: lbzu `ppc64 ~d_addr:20 ~value:0x42; + "lbzu64 -imm" >:: lbzu `ppc64 ~d_addr:(-16) ~value:0x42; + "lhzu64 +imm" >:: lhzu `ppc64 ~d_addr:20 ~value:0x4242; + "lhzu64 -imm" >:: lhzu `ppc64 ~d_addr:(-16) ~value:0x4252; + "lwzu64 +imm" >:: lwzu `ppc64 ~d_addr:20 ~value:0xAAAA4242; + "lwzu64 -imm" >:: lwzu `ppc64 ~d_addr:(-16) ~value:0xAAAA4252; + + "lbzux64" >:: lbzux `ppc64 ~value:0x42; + "lhzux64" >:: lhzux `ppc64 ~value:0x4242; + "lwzux64" >:: lwzux `ppc64 ~value:0xAAAA4242; + + "lha64" >:: lha `ppc64; + "lhax64" >:: lhax `ppc64; + "lhau64" >:: lhau `ppc64; + "lhaux64" >:: lhaux `ppc64; + "lwa64" >:: lwa `ppc64; + "lwax64" >:: lwax `ppc64; + "lwaux64" >:: lwaux `ppc64; + "ld64" >:: ld; + "ldx64" >:: ldx; + "ldu64" >:: ldu; + "ldux64" >:: ldux; + "ldux64a" >:: ldux_big_addr; + + "lhbrx64" >:: lhbrx `ppc64; + "lwbrx64" >:: lwbrx `ppc64; + "ldbrx64" >:: ldbrx; + ] diff --git a/lib_test/powerpc/powerpc_logical_tests.ml b/lib_test/powerpc/powerpc_logical_tests.ml new file mode 100644 index 000000000..b7f350aec --- /dev/null +++ b/lib_test/powerpc/powerpc_logical_tests.ml @@ -0,0 +1,636 @@ +open Core_kernel.Std +open Bap.Std +open OUnit2 + +open Powerpc_tests_helpers + +let andi_dot arch ctxt = + let bytes = "\x71\x2a\x00\x1F" in (** andi. r10,r9,31 *) + let r10 = find_gpr arch "R10" in + let r9 = find_gpr arch "R9" in + let width = arch_width arch in + let init = Bil.[ + r9 := int (Word.of_int ~width 10); + ] in + let expected = Word.of_int ~width 10 in + check_gpr init bytes r10 expected arch ctxt + +let andis_dot arch ctxt = + let bytes = "\x75\x2a\x0E\x00" in (** andis. r10,r9,2048 *) + let r10 = find_gpr arch "R10" in + let r9 = find_gpr arch "R9" in + let width = arch_width arch in + let value = Word.of_int ~width 0x0800_0000 in + let init = Bil.[ + r9 := int value; + ] in + let expected = value in + check_gpr init bytes r10 expected arch ctxt + +let and_ arch ctxt = + let bytes = "\x7f\x39\xe8\x38" in (** and r25 r25 r29 *) + let r25 = find_gpr arch "R25" in + let r29 = find_gpr arch "R29" in + let width = arch_width arch in + let x = 31 in + let y = 10 in + let r = x land y in + let init = Bil.[ + r29 := int (Word.of_int ~width x); + r25 := int (Word.of_int ~width y); + ] in + let expected = Word.of_int ~width r in + check_gpr init bytes r25 expected arch ctxt + +let and_dot arch ctxt = + let bytes = "\x7f\x39\xe8\x39" in (** and. r25 r25 r29 *) + let r25 = find_gpr arch "R25" in + let r29 = find_gpr arch "R29" in + let width = arch_width arch in + let x = 31 in + let y = 10 in + let r = x land y in + let init = Bil.[ + r29 := int (Word.of_int ~width x); + r25 := int (Word.of_int ~width y); + ] in + let ctxt = eval init bytes arch in + let r25_value = lookup_var ctxt r25 in + let expected = Word.of_int ~width r in + let nf_value = lookup_var ctxt nf in + let pf_value = lookup_var ctxt pf in + let zf_value = lookup_var ctxt zf in + assert_bool "add. failed" (is_equal_words expected r25_value); + assert_bool "addc. failed" (is_equal_words Word.b0 nf_value); + assert_bool "addc. failed" (is_equal_words Word.b1 pf_value); + assert_bool "addc. failed" (is_equal_words Word.b0 zf_value) + +let andc arch ctxt = + let bytes = "\x7c\xea\x50\x78" in (** andc r10 r7 r10 *) + let r10 = find_gpr arch "R10" in + let r7 = find_gpr arch "R7" in + let width = arch_width arch in + let x = 21 in + let y = 10 in + let r = x land (lnot y) in + let init = Bil.[ + r7 := int (Word.of_int ~width x); + r10 := int (Word.of_int ~width y); + ] in + let expected = Word.of_int ~width r in + check_gpr init bytes r10 expected arch ctxt + +let andc_dot arch ctxt = + let bytes = "\x7c\xea\x50\x79" in (** andc. r10 r7 r10 *) + let r10 = find_gpr arch "R10" in + let r7 = find_gpr arch "R7" in + let width = arch_width arch in + let x = 42 in + let y = x in + let r = x land (lnot y) in + let init = Bil.[ + r7 := int (Word.of_int ~width x); + r10 := int (Word.of_int ~width y); + ] in + let ctxt = eval init bytes arch in + let r10_value = lookup_var ctxt r10 in + let expected = Word.of_int ~width r in + let nf_value = lookup_var ctxt nf in + let pf_value = lookup_var ctxt pf in + let zf_value = lookup_var ctxt zf in + assert_bool "addc. failed" (is_equal_words expected r10_value); + assert_bool "addc. failed" (is_equal_words Word.b0 nf_value); + assert_bool "addc. failed" (is_equal_words Word.b0 pf_value); + assert_bool "addc. failed" (is_equal_words Word.b1 zf_value) + +let ori arch ctxt = + let bytes = "\x60\xc6\x51\xc1" in (** ori r6,r6,20929 *) + let r6 = find_gpr arch "R6" in + let width = arch_width arch in + let x = 62 in + let r = x lor 20929 in + let init = Bil.[ + r6 := int (Word.of_int ~width x); + ] in + let expected = Word.of_int ~width r in + check_gpr init bytes r6 expected arch ctxt + +let oris arch ctxt = + let bytes = "\x65\x4a\x00\x0F" in (** oris r10,r10,15 *) + let r10 = find_gpr arch "R10" in + let width = arch_width arch in + let x = 61440 in + let y = 15 in + let r = x lxor (y lsl 16) in + let init = Bil.[ + r10 := int (Word.of_int ~width x); + ] in + let expected = Word.of_int ~width r in + check_gpr init bytes r10 expected arch ctxt + +let or_ arch ctxt = + let bytes = "\x7f\x38\xc3\x78" in (** or r24,r25,r24 *) + let r24 = find_gpr arch "R24" in + let r25 = find_gpr arch "R25" in + let width = arch_width arch in + let x = 24 in + let y = 10 in + let r = x lor y in + let init = Bil.[ + r24 := int (Word.of_int ~width x); + r25 := int (Word.of_int ~width y); + ] in + let expected = Word.of_int ~width r in + check_gpr init bytes r24 expected arch ctxt + +let or_dot arch ctxt = + let bytes = "\x7f\x38\xc3\x79" in (** or r24,r25,r24 *) + let r24 = find_gpr arch "R24" in + let r25 = find_gpr arch "R25" in + let width = arch_width arch in + let x = 24 in + let y = 10 in + let r = x lor y in + let init = Bil.[ + r24 := int (Word.of_int ~width x); + r25 := int (Word.of_int ~width y); + ] in + let ctxt = eval init bytes arch in + let r24_value = lookup_var ctxt r24 in + let expected = Word.of_int ~width r in + let nf_value = lookup_var ctxt nf in + let pf_value = lookup_var ctxt pf in + let zf_value = lookup_var ctxt zf in + assert_bool "or. failed" (is_equal_words expected r24_value); + assert_bool "or. failed" (is_equal_words Word.b0 nf_value); + assert_bool "or. failed" (is_equal_words Word.b1 pf_value); + assert_bool "or. failed" (is_equal_words Word.b0 zf_value) + +let orc arch ctxt = + let bytes = "\x7c\x8a\x53\x38" in (** orc r10,r4,r10 *) + let r4 = find_gpr arch "R4" in + let r10 = find_gpr arch "R10" in + let width = arch_width arch in + let x = 42 in + let y = 10 in + let r = x lor (lnot y) in + let init = Bil.[ + r4 := int (Word.of_int ~width x); + r10 := int (Word.of_int ~width y); + ] in + let expected = Word.of_int ~width r in + check_gpr init bytes r10 expected arch ctxt + +let orc_dot arch ctxt = + let bytes = "\x7c\x8a\x53\x39" in (** orc. r10,r4,r10 *) + let r4 = find_gpr arch "R4" in + let r10 = find_gpr arch "R10" in + let width = arch_width arch in + let x = 42 in + let y = 0 in + let r = x lor (lnot y) in + let init = Bil.[ + r4 := int (Word.of_int ~width x); + r10 := int (Word.of_int ~width y); + ] in + let ctxt = eval init bytes arch in + let r10_value = lookup_var ctxt r10 in + let expected = Word.of_int ~width r in + let nf_value = lookup_var ctxt nf in + let pf_value = lookup_var ctxt pf in + let zf_value = lookup_var ctxt zf in + assert_bool "orc. failed" (is_equal_words expected r10_value); + assert_bool "orc. failed" (is_equal_words Word.b1 nf_value); + assert_bool "orc. failed" (is_equal_words Word.b0 pf_value); + assert_bool "orc. failed" (is_equal_words Word.b0 zf_value) + +let xori arch ctxt = + let bytes = "\x68\x63\x00\x0B" in (** xori r3,r3,11 *) + let r3 = find_gpr arch "R3" in + let width = arch_width arch in + let x = 16 in + let r = x lxor 11 in + let init = Bil.[ + r3 := int (Word.of_int ~width x); + ] in + let expected = Word.of_int ~width r in + check_gpr init bytes r3 expected arch ctxt + +let xoris arch ctxt = + let bytes = "\x6d\x2a\x00\x0f" in (** xoris r10,r9,15 *) + let r9 = find_gpr arch "R9" in + let r10 = find_gpr arch "R10" in + let width = arch_width arch in + let x = 0x1F0000 in + let r = x lxor (15 lsl 16) in + let init = Bil.[ + r9 := int (Word.of_int ~width x); + ] in + let expected = Word.of_int ~width r in + check_gpr init bytes r10 expected arch ctxt + +let xor_ arch ctxt = + let bytes = "\x7c\x6a\x52\x78" in (** xor r10,r3,r10 *) + let r3 = find_gpr arch "R3" in + let r10 = find_gpr arch "R10" in + let width = arch_width arch in + let x = 42 in + let y = 15 in + let r = x lxor y in + let init = Bil.[ + r3 := int (Word.of_int ~width x); + r10 := int (Word.of_int ~width y); + ] in + let expected = Word.of_int ~width r in + check_gpr init bytes r10 expected arch ctxt + +let xor_dot arch ctxt = + let bytes = "\x7c\x6a\x52\x79" in (** xor. r10,r3,r10 *) + let r3 = find_gpr arch "R3" in + let r10 = find_gpr arch "R10" in + let width = arch_width arch in + let x = 42 in + let y = 42 in + let r = x lxor y in + let init = Bil.[ + r3 := int (Word.of_int ~width x); + r10 := int (Word.of_int ~width y); + ] in + let ctxt = eval init bytes arch in + let r10_value = lookup_var ctxt r10 in + let expected = Word.of_int ~width r in + let nf_value = lookup_var ctxt nf in + let pf_value = lookup_var ctxt pf in + let zf_value = lookup_var ctxt zf in + assert_bool "xor. failed" (is_equal_words expected r10_value); + assert_bool "xor. failed" (is_equal_words Word.b0 nf_value); + assert_bool "xor. failed" (is_equal_words Word.b0 pf_value); + assert_bool "xor. failed" (is_equal_words Word.b1 zf_value) + +let nand arch ctxt = + let bytes = "\x7c\x63\x23\xb8" in (** nand r3,r3,r4 *) + let r3 = find_gpr arch "R3" in + let r4 = find_gpr arch "R4" in + let width = arch_width arch in + let x = 42 in + let y = 15 in + let r = lnot (x land y) in + let init = Bil.[ + r3 := int (Word.of_int ~width x); + r4 := int (Word.of_int ~width y); + ] in + let expected = Word.of_int ~width r in + check_gpr init bytes r3 expected arch ctxt + +let nand_dot arch ctxt = + let bytes = "\x7c\x63\x23\xb9" in (** nand. r3,r3,r4 *) + let r3 = find_gpr arch "R3" in + let r4 = find_gpr arch "R4" in + let width = arch_width arch in + let x = 42 in + let y = 15 in + let r = lnot (x land y) in + let init = Bil.[ + r3 := int (Word.of_int ~width x); + r4 := int (Word.of_int ~width y); + ] in + let ctxt = eval init bytes arch in + let r3_value = lookup_var ctxt r3 in + let expected = Word.of_int ~width r in + let nf_value = lookup_var ctxt nf in + let pf_value = lookup_var ctxt pf in + let zf_value = lookup_var ctxt zf in + assert_bool "nand. failed" (is_equal_words expected r3_value); + assert_bool "nand. failed" (is_equal_words Word.b1 nf_value); + assert_bool "nand. failed" (is_equal_words Word.b0 pf_value); + assert_bool "nand. failed" (is_equal_words Word.b0 zf_value) + +let nor arch ctxt = + let bytes = "\x7d\x09\x48\xf8" in (** nor r9,r8,r9 *) + let r8 = find_gpr arch "R8" in + let r9 = find_gpr arch "R9" in + let width = arch_width arch in + let x = 42 in + let y = 15 in + let r = lnot (x lor y) in + let init = Bil.[ + r8 := int (Word.of_int ~width x); + r9 := int (Word.of_int ~width y); + ] in + let expected = Word.of_int ~width r in + check_gpr init bytes r9 expected arch ctxt + +let nor_dot arch ctxt = + let bytes = "\x7d\x09\x48\xf9" in (** nor. r9,r8,r9 *) + let r8 = find_gpr arch "R8" in + let r9 = find_gpr arch "R9" in + let width = arch_width arch in + let x = 42 in + let y = -15 in + let r = lnot (x lor y) in + let init = Bil.[ + r8 := int (Word.of_int ~width x); + r9 := int (Word.of_int ~width y); + ] in + let ctxt = eval init bytes arch in + let r9_value = lookup_var ctxt r9 in + let expected = Word.of_int ~width r in + let nf_value = lookup_var ctxt nf in + let pf_value = lookup_var ctxt pf in + let zf_value = lookup_var ctxt zf in + assert_bool "nor. failed" (is_equal_words expected r9_value); + assert_bool "nor. failed" (is_equal_words Word.b0 nf_value); + assert_bool "nor. failed" (is_equal_words Word.b1 pf_value); + assert_bool "nor. failed" (is_equal_words Word.b0 zf_value) + +let eqv arch ctxt = + let bytes = "\x7d\x09\x4a\x38" in (** eqv r9,r8,r9 *) + let r8 = find_gpr arch "R8" in + let r9 = find_gpr arch "R9" in + let width = arch_width arch in + let x = 42 in + let y = 15 in + let r = lnot (x lxor y); in + let init = Bil.[ + r8 := int (Word.of_int ~width x); + r9 := int (Word.of_int ~width y); + ] in + let expected = Word.of_int ~width r in + check_gpr init bytes r9 expected arch ctxt + +let eqv_dot arch ctxt = + let bytes = "\x7d\x09\x4a\x39" in (** eqv. r9,r8,r9 *) + let r8 = find_gpr arch "R8" in + let r9 = find_gpr arch "R9" in + let width = arch_width arch in + let x = -1 in + let y = 0 in + let r = lnot (x lxor y); in + let init = Bil.[ + r8 := int (Word.of_int ~width x); + r9 := int (Word.of_int ~width y); + ] in + let ctxt = eval init bytes arch in + let r9_value = lookup_var ctxt r9 in + let expected = Word.of_int ~width r in + let nf_value = lookup_var ctxt nf in + let pf_value = lookup_var ctxt pf in + let zf_value = lookup_var ctxt zf in + assert_bool "eqv. failed" (is_equal_words expected r9_value); + assert_bool "eqv. failed" (is_equal_words Word.b0 nf_value); + assert_bool "eqv. failed" (is_equal_words Word.b0 pf_value); + assert_bool "eqv. failed" (is_equal_words Word.b1 zf_value) + +let extsb arch ctxt = + let bytes = "\x7d\x6a\x07\x74" in (** extsb r10,r11 *) + let r10 = find_gpr arch "R10" in + let r11 = find_gpr arch "R11" in + let width = arch_width arch in + let init = Bil.[ + r11 := int (Word.of_int ~width 0xC0); + ] in + let expected = Word.of_int64 ~width 0xFFFFFFFFFFFFFFC0L in + check_gpr init bytes r10 expected arch ctxt + +let extsh arch ctxt = + let bytes = "\x7d\x25\x07\x34" in (** extsh r5,r9 *) + let r5 = find_gpr arch "R5" in + let r9 = find_gpr arch "R9" in + let width = arch_width arch in + let init = Bil.[ + r9 := int (Word.of_int ~width 0xC000); + ] in + let expected = Word.of_int64 ~width 0xFFFFFFFFFFFFC000L in + check_gpr init bytes r5 expected arch ctxt + +let exts_dot arch ctxt = + let bytes = "\x7d\x25\x07\x35" in (** extsh. r5,r9 *) + let r5 = find_gpr arch "R5" in + let r9 = find_gpr arch "R9" in + let width = arch_width arch in + let init = Bil.[ + r9 := int (Word.of_int ~width 0xC000); + ] in + let expected = Word.of_int64 ~width 0xFFFFFFFFFFFFC000L in + let ctxt = eval init bytes arch in + let r5_value = lookup_var ctxt r5 in + let nf_value = lookup_var ctxt nf in + let pf_value = lookup_var ctxt pf in + let zf_value = lookup_var ctxt zf in + assert_bool "extsh. failed" (is_equal_words expected r5_value); + assert_bool "extsh. failed" (is_equal_words Word.b1 nf_value); + assert_bool "extsh. failed" (is_equal_words Word.b0 pf_value); + assert_bool "extsh. failed" (is_equal_words Word.b0 zf_value) + +let extsw arch ctxt = + let bytes = "\x7d\x25\x07\xb4" in (** extsw r5,r9 *) + let r5 = find_gpr arch "R5" in + let r9 = find_gpr arch "R9" in + let width = arch_width arch in + let init = Bil.[ + r9 := int (Word.of_int ~width 0xC0000000); + ] in + let expected = Word.of_int64 ~width 0xFFFFFFFFC0000000L in + check_gpr init bytes r5 expected arch ctxt + +let extsw_dot arch ctxt = + let bytes = "\x7d\x25\x07\xb5" in (** extsw. r5,r9 *) + let r5 = find_gpr arch "R5" in + let r9 = find_gpr arch "R9" in + let width = arch_width arch in + let init = Bil.[ + r9 := int (Word.of_int ~width 0xC0000000); + ] in + let expected = Word.of_int64 ~width 0xFFFFFFFFC0000000L in + check_gpr init bytes r5 expected arch ctxt + +let cntlzw arch value zeros ctxt = + let bytes = "\x7c\x63\x00\x34" in + let r = find_gpr arch "R3" in + let width = arch_width arch in + let init = Bil.[ + r := int (Word.of_int ~width value); + ] in + let expected = Word.of_int ~width zeros in + check_gpr init bytes r expected arch ctxt + +let cnttzw arch value zeros ctxt = + let bytes = "\x7c\x63\x04\x34" in + let r = find_gpr arch "R3" in + let width = arch_width arch in + let init = Bil.[ + r := int (Word.of_int ~width value); + ] in + let expected = Word.of_int ~width zeros in + check_gpr init bytes r expected arch ctxt + +let cntlzd ctxt = + let arch = `ppc64 in + let bytes = "\x7c\x63\x00\x74" in + let r = find_gpr arch "R3" in + let width = arch_width arch in + let value = Word.of_int64 0x0000FFFF_00000000L in + let init = Bil.[ + r := int value; + ] in + let expected = Word.of_int ~width 16 in + check_gpr init bytes r expected arch ctxt + +let cnttzd ctxt = + let arch = `ppc64 in + let bytes = "\x7c\x63\x04\x75" in + let r = find_gpr arch "R3" in + let width = arch_width arch in + let value = Word.of_int64 0x00000000_FFFF0000L in + let init = Bil.[ + r := int value; + ] in + let expected = Word.of_int ~width 16 in + check_gpr init bytes r expected arch ctxt + +let cmpb arch ~bytes_cnt x y expected ctxt = + let bytes = "\x7c\x8a\x53\xf8" in + let width = arch_width arch in + let x = Word.of_int ~width x in + let y = Word.of_int ~width y in + let r10 = find_gpr arch "R10" in + let r4 = find_gpr arch "R4" in + let init = Bil.[ + r10 := int x; + r4 := int y; + ] in + let head = Word.ones (width - bytes_cnt * 8) in + let expected = Word.of_int ~width:(bytes_cnt * 8) expected in + let expected = Word.concat head expected in + check_gpr init bytes r10 expected arch ctxt + +let popcntw arch ctxt = + let bytes = "\x7c\x44\x02\xf4" in (** popcntw r4, r2 *) + let r4 = find_gpr arch "R4" in + let r2 = find_gpr arch "R2" in + let width = arch_width arch in + let value,expected = match arch with + | `ppc -> + Word.of_int64 ~width 0x10000001L, + Word.of_int64 ~width 0x000000002L + | _ -> + Word.of_int64 0xA0200040_10000001L, + Word.of_int64 0x400000002L in (** 4 bits set in first word, and 2 in second *) + let init = Bil.[ + r2 := int value; + ] in + check_gpr init bytes r4 expected arch ctxt + +let popcntd ctxt = + let arch = `ppc64 in + let bytes = "\x7c\x44\x03\xf4" in (** popcntw r4, r2 *) + let r4 = find_gpr arch "R4" in + let r2 = find_gpr arch "R2" in + let width = arch_width arch in + let value = Word.of_int64 0x0F00000F_00000001L in + let expected = Word.of_int ~width 9 in + let init = Bil.[ + r2 := int value; + ] in + check_gpr init bytes r4 expected arch ctxt + +let bperm ctxt = + let arch = `ppc64 in + let bytes = "\x7c\xa1\x49\xf8" in (** bpermd r1, r5, r9 *) + let r1 = find_gpr arch "R1" in + let r5 = find_gpr arch "R5" in + let r9 = find_gpr arch "R9" in + let width = arch_width arch in + let index_bits = Word.of_int64 0x05_00_01_44_25_1B_02_04L in + let value = Word.of_int64 0xFFABCDEF0A0B0C0DL in + let expected = Word.of_int ~width 0xe3 in + let init = Bil.[ + r5 := int index_bits; + r9 := int value; + ] in + check_gpr init bytes r1 expected arch ctxt + +let suite = "logical" >::: [ + "andi.32" >:: andi_dot `ppc; + "andis.32" >:: andis_dot `ppc; + "and32" >:: and_ `ppc; + "and.32" >:: and_dot `ppc; + "andc32" >:: andc `ppc; + "andc.32" >:: andc_dot `ppc; + "ori32" >:: ori `ppc; + "oris32" >:: oris `ppc; + "or32" >:: or_ `ppc; + "or.32" >:: or_dot `ppc; + "orc32" >:: orc `ppc; + "orc.32" >:: orc_dot `ppc; + "xori32" >:: xori `ppc; + "xoris23" >:: xoris `ppc; + "xor32" >:: xor_ `ppc; + "xor.32" >:: xor_dot `ppc; + "nand32" >:: nand `ppc; + "nand.32" >:: nand_dot `ppc; + "nor32" >:: nor `ppc; + "nor.32" >:: nor_dot `ppc; + "eqv32" >:: eqv `ppc; + "eqv.32" >:: eqv_dot `ppc; + "extsb32" >:: extsb `ppc; + "extsh32" >:: extsh `ppc; + "extsw32" >:: extsw `ppc; + "exts.32" >:: exts_dot `ppc; + "cntlzw32: 1" >:: cntlzw `ppc 0x0 32; + "cntlzw32: 2" >:: cntlzw `ppc 0x4000000 5; + "cntlzw32: 3" >:: cntlzw `ppc 0x40000000 1; + "cntlzw32: 4" >:: cntlzw `ppc 0x80000000 0; + "cnttzw32: 1" >:: cnttzw `ppc 0x0 32; + "cnttzw32: 2" >:: cnttzw `ppc 0x1 0; + "cnttzw32: 3" >:: cnttzw `ppc 0x2 1; + "cnttzw32: 4" >:: cnttzw `ppc 0x20 5; + "cmpb32: 0" >:: cmpb `ppc ~bytes_cnt:3 0x31_41_AD 0x34_42_AD 0x00_00_FF; + "cmpb32: 1" >:: cmpb `ppc ~bytes_cnt:3 0x31_42_45 0x34_42_AD 0x00_FF_00; + "cmpb32: 2" >:: cmpb `ppc ~bytes_cnt:3 0 0x34_42_AD 0x0; + "cmpb32: 3" >:: cmpb `ppc ~bytes_cnt:3 0x34_42_AD 0x34_42_AD 0xFF_FF_FF; + "popcntw32" >:: popcntw `ppc; + + "andi.64" >:: andi_dot `ppc64; + "andis.64" >:: andis_dot `ppc64; + "and64" >:: and_ `ppc64; + "and.64" >:: and_dot `ppc64; + "andc64" >:: andc `ppc64; + "andc.64" >:: andc_dot `ppc64; + "ori64" >:: ori `ppc64; + "oris64" >:: oris `ppc64; + "or64" >:: or_ `ppc64; + "or.64" >:: or_dot `ppc64; + "orc64" >:: orc `ppc64; + "orc.64" >:: orc_dot `ppc64; + "xori64" >:: xori `ppc64; + "xoris64" >:: xoris `ppc64; + "xor64" >:: xor_ `ppc64; + "xor.64" >:: xor_dot `ppc64; + "nand64" >:: nand `ppc64; + "nand.64" >:: nand_dot `ppc64; + "nor64" >:: nor `ppc64; + "nor.64" >:: nor_dot `ppc64; + "eqv64" >:: eqv `ppc64; + "eqv.64" >:: eqv_dot `ppc64; + "extsb64" >:: extsb `ppc64; + "extsh64" >:: extsh `ppc64; + "extsw64" >:: extsw `ppc64; + "exts.64" >:: exts_dot `ppc64; + "cntlz64: 1" >:: cntlzw `ppc64 0x0 32; + "cntlz64: 2" >:: cntlzw `ppc64 0x4000000 5; + "cntlz64: 3" >:: cntlzw `ppc64 0x40000000 1; + "cntlz64: 4" >:: cntlzw `ppc64 0x80000000 0; + "cnttz64: 1" >:: cnttzw `ppc64 0x0 32; + "cnttz64: 2" >:: cnttzw `ppc64 0x1 0; + "cnttz64: 3" >:: cnttzw `ppc64 0x2 1; + "cnttz64: 4" >:: cnttzw `ppc64 0x20 5; + "cntlzd" >:: cntlzd; + "cnttzd" >:: cnttzd; + "cmpb64: 1" >:: cmpb `ppc64 ~bytes_cnt:3 0x31_42_45 0x34_42_AD 0x00_FF_00; + "cmpb64: 2" >:: cmpb `ppc64 ~bytes_cnt:3 0 0x34_42_AD 0x0; + "cmpb64: 3" >:: cmpb `ppc64 ~bytes_cnt:3 0x34_42_AD 0x34_42_AD 0xFF_FF_FF; + "popcntw64" >:: popcntw `ppc64; + "popcntd" >:: popcntd; + "bperm64" >:: bperm; + ] diff --git a/lib_test/powerpc/powerpc_move_tests.ml b/lib_test/powerpc/powerpc_move_tests.ml new file mode 100644 index 000000000..4a13f8379 --- /dev/null +++ b/lib_test/powerpc/powerpc_move_tests.ml @@ -0,0 +1,94 @@ +open Core_kernel.Std +open Bap.Std +open OUnit2 + +open Powerpc_tests_helpers + +let mtspr arch ctxt = + let name = "MTSPR" in + let anybit = 0 in + let bytes = make_insn ~name `XFX [31; 1; 9; 467; anybit] in + let r1 = find_gpr arch "R1" in + let width = arch_width arch in + let x = 0xABCDEFAB_12345678L in + let data = Word.of_int64 ~width x in + let init = Bil.[ + r1 := int data; + ] in + let expected = match arch with + | `ppc -> Word.extract_exn ~hi:31 data + | _ -> data in + check_gpr init bytes (ctr arch) expected arch ctxt + +let mfspr arch ctxt = + let name = "MFSPR" in + let anybit = 0 in + let bytes = make_insn ~name `XFX [31; 1; 8; 339; anybit] in + let r1 = find_gpr arch "R1" in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xABCDEFAB_12345678L in + let lr = lr arch in + let init = Bil.[ + lr := int x; + ] in + let expected = match arch with + | `ppc -> Word.extract_exn ~hi:31 x + | _ -> x in + check_gpr init bytes r1 expected arch ctxt + +let mtcrf arch _ctxt = + let name = "MTCRF" in + let anybit = 0 in + let mask = 0b01101001 in + let set_bits = [1;2;4;7] in + let bytes = make_insn ~name `XFX [31; 1; 0; mask; anybit; 144; anybit] in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xABCDEFAB_12345678L in + let r1 = find_gpr arch "R1" in + let init = Bil.[ + r1 := int x; + ] in + let b0 = Bil.int Word.b0 in + let init_cr = Map.fold cri ~init:[] + ~f:(fun ~key:_ ~data:bit acc -> Bil.(bit := b0) :: acc) in + let init = init @ init_cr in + let ctxt = eval init bytes arch in + let range = List.range 0 32 in + let r1_bits = Word.enum_bits (Word.extract_exn ~hi:31 x) BigEndian in + let r1_bits = Seq.to_array r1_bits in + List.iter range ~f:(fun i -> + if List.exists set_bits ~f:(fun j -> + j*4 <= i && i < (j + 1) * 4) then + let expected = + if r1_bits.(i) then Word.b1 else Word.b0 in + let cr_bit = Int.Map.find_exn cri i in + let value = lookup_var ctxt cr_bit in + let err = sprintf "mtcrf assign to bit %d failed\n" i in + assert_bool err (is_equal_words expected value)) + +let mfcr arch ctxt = + let name = "MFCR" in + let bytes = make_insn ~name `XFX [31; 1; 0; 0;0; 19; 0] in + let width = arch_width arch in + let r1 = find_gpr arch "R1" in + let x = Word.of_int64 ~width:32 0x12345678L in + let bits = Seq.to_list @@ Word.enum_bits x BigEndian in + let init = List.foldi bits ~init:[] + ~f:(fun i acc bit -> + let w = if bit then Word.b1 else Word.b0 in + let b = Map.find_exn cri i in + Bil.(b := int w) :: acc) in + let expected = Word.extract_exn ~hi:(width - 1) x in + check_gpr init bytes r1 expected arch ctxt + +let suite = "move" >::: [ + "mtspr" >:: mtspr `ppc; + "mfspr" >:: mfspr `ppc; + "mtcrf" >:: mtcrf `ppc; + "mfcr" >:: mfcr `ppc; + + "mtspr 64" >:: mtspr `ppc64; + "mfspr 64" >:: mfspr `ppc64; + "mtcrf 64" >:: mtcrf `ppc64; + "mfcr 64" >:: mfcr `ppc64 + ] diff --git a/lib_test/powerpc/powerpc_rotate_tests.ml b/lib_test/powerpc/powerpc_rotate_tests.ml new file mode 100644 index 000000000..c5c36342b --- /dev/null +++ b/lib_test/powerpc/powerpc_rotate_tests.ml @@ -0,0 +1,311 @@ +open Core_kernel.Std +open OUnit2 +open Bap.Std + +open Powerpc_tests_helpers + +let circ_shift32 x sh = + if sh = 0 then x + else + let width = Word.bitwidth x in + let x = Word.extract_exn ~hi:31 x in + let x = Word.concat x x in + let bits = Word.bitwidth x in + let right = Word.extract_exn ~lo:(bits - sh) x in + Word.extract_exn ~hi:(width - 1) (Word.concat x right) + +let mask64 start stop = + let make f w = + if w > 0 then Some (f w) + else None in + let (^) = Word.concat in + let concat x y z = + match List.filter_map ~f:ident [x;y;z;] with + | [x] -> x + | [x;y] -> x ^ y + | [x;y;z;] -> x ^ y ^ z + | _ -> failwith "list is empty" in + let width = 64 in + if start <= stop then + let a1 = make Word.zero start in + let a2 = make Word.ones (stop - start + 1) in + let a3 = make Word.zero (width - stop - 1) in + concat a1 a2 a3 + else + let a1 = make Word.ones stop in + let a2 = make Word.zero (start - stop + 1) in + let a3 = make Word.ones (width - start - 1) in + concat a1 a2 a3 + +let mask32 width start stop = + Word.extract_exn ~hi:(width - 1) @@ + mask64 (start + 32) (stop + 32) + +let circ_shift64 x sh = + if sh = 0 then x + else + let bits = Word.bitwidth x in + let right = Word.extract_exn ~lo:(bits - sh) x in + Word.extract_exn ~hi:(bits - 1) (Word.concat x right) + +let rlwinm arch ~sh ~from ~to_ ctxt = + let name = "RLWINM" in + let bytes = make_insn ~name `M [21; 9; 10; sh; from; to_; 0] in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xAABBCCDDL in + let r9 = find_gpr arch "R9" in + let r10 = find_gpr arch "R10" in + let init = Bil.[ + r9 := int x; + ] in + let shifted = circ_shift32 x sh in + let mask = mask32 width from to_ in + let expected = Word.(shifted land mask) in + check_gpr init bytes r10 expected arch ctxt + +let rlwnm arch ~sh ~from ~to_ ctxt = + let name = "RLWNM" in + let bytes = make_insn ~name `M [23; 9; 10; 3; from; to_; 0] in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xAABBCCDDL in + let shw = Word.of_int ~width sh in + let r3 = find_gpr arch "R3" in + let r9 = find_gpr arch "R9" in + let r10 = find_gpr arch "R10" in + let init = Bil.[ + r3 := int shw; + r9 := int x; + ] in + let shifted = circ_shift32 x sh in + let mask = mask32 width from to_ in + let expected = Word.(shifted land mask) in + check_gpr init bytes r10 expected arch ctxt + +let rlwimi arch ~sh ~from ~to_ ctxt = + let name = "RLWIMI" in + let bytes = make_insn ~name `M [20; 9; 10; sh; from; to_; 0] in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xAABBCCDDL in + let y = Word.of_int64 ~width 0xAABBCCDD_FFEEAA42L in + let r9 = find_gpr arch "R9" in + let r10 = find_gpr arch "R10" in + let init = Bil.[ + r9 := int x; + r10 := int y; + ] in + let shifted = circ_shift32 x sh in + let mask = mask32 width from to_ in + let expected = Word.((shifted land mask) lor (y land (lnot mask))) in + check_gpr init bytes r10 expected arch ctxt + +let extract_from_int hi lo v = + let w = Word.of_int ~width:32 v in + let w'= Word.extract_exn ~hi ~lo w in + Word.to_int_exn w' + +let swap_msb x = + let x = Word.of_int ~width:32 x in + let b1 = Word.extract_exn ~hi:5 ~lo:5 x in + let b2 = Word.extract_exn ~hi:4 x in + let y = Word.concat b2 b1 in + Word.to_int_exn y + +let rldicl ~sh ~from ctxt = + let arch = `ppc64 in + let name = "RLDICL" in + let sh0_4 = extract_from_int 4 0 sh in + let sh5 = extract_from_int 5 5 sh in + let from' = swap_msb from in + let bytes = make_insn ~name `MD [30; 9; 10; sh0_4; from'; 0; sh5; 0] in + let x = Word.of_int64 0xAABBCCDD_4242FFAAL in + let r9 = find_gpr arch "R9" in + let r10 = find_gpr arch "R10" in + let init = Bil.[ + r9 := int x; + ] in + let shifted = circ_shift64 x sh in + let mask = mask64 from 63 in + let expected = Word.(shifted land mask) in + check_gpr init bytes r10 expected arch ctxt + +let rldicr ~sh ~to_ ctxt = + let arch = `ppc64 in + let name = "RLDICR" in + let sh0_4 = extract_from_int 4 0 sh in + let sh5 = extract_from_int 5 5 sh in + let to' = swap_msb to_ in + let bytes = make_insn ~name `MD [30; 9; 10; sh0_4; to'; 1; sh5; 0] in + let x = Word.of_int64 0xAABBCCDD_4242FFAAL in + let r9 = find_gpr arch "R9" in + let r10 = find_gpr arch "R10" in + let init = Bil.[ + r9 := int x; + ] in + let shifted = circ_shift64 x sh in + let mask = mask64 0 to_ in + let expected = Word.(shifted land mask) in + check_gpr init bytes r10 expected arch ctxt + +let rldic ~sh ~from ctxt = + let arch = `ppc64 in + let name = "RLDIC" in + let sh0_4 = extract_from_int 4 0 sh in + let sh5 = extract_from_int 5 5 sh in + let from' = swap_msb from in + let bytes = make_insn ~name `MD [30; 9; 10; sh0_4; from'; 2; sh5; 0] in + let x = Word.of_int64 0xAABBCCDD_4242FFAAL in + let r9 = find_gpr arch "R9" in + let r10 = find_gpr arch "R10" in + let init = Bil.[ + r9 := int x; + ] in + let shifted = circ_shift64 x sh in + let mask = mask64 from (63 - sh) in + let expected = Word.(shifted land mask) in + check_gpr init bytes r10 expected arch ctxt + +let rldcl ~sh ~from ctxt = + let arch = `ppc64 in + let name = "RLDCL" in + let from' = swap_msb from in + let bytes = make_insn ~name `MDS [30; 9; 10; 11; from'; 8; 0] in + let shw = Word.of_int ~width:64 sh in + let x = Word.of_int64 0xAABBCCDD_4242FFAAL in + let r9 = find_gpr arch "R9" in + let r11 = find_gpr arch "R11" in + let r10 = find_gpr arch "R10" in + let init = Bil.[ + r9 := int x; + r11 := int shw; + ] in + let shifted = circ_shift64 x sh in + let mask = mask64 from 63 in + let expected = Word.(shifted land mask) in + check_gpr init bytes r10 expected arch ctxt + +let rldcr ~sh ~to_ ctxt = + let arch = `ppc64 in + let name = "RLDCR" in + let to' = swap_msb to_ in + let bytes = make_insn ~name `MDS [30; 9; 10; 11; to'; 9; 0] in + let x = Word.of_int64 0xAABBCCDD_4242FFAAL in + let shw = Word.of_int ~width:64 sh in + let r9 = find_gpr arch "R9" in + let r10 = find_gpr arch "R10" in + let r11 = find_gpr arch "R11" in + let init = Bil.[ + r9 := int x; + r11 := int shw; + ] in + let shifted = circ_shift64 x sh in + let mask = mask64 0 to_ in + let expected = Word.(shifted land mask) in + check_gpr init bytes r10 expected arch ctxt + +let rldimi ~sh ~from ctxt = + let arch = `ppc64 in + let name = "RLDIMI" in + let sh0_4 = extract_from_int 4 0 sh in + let sh5 = extract_from_int 5 5 sh in + let from' = swap_msb from in + let bytes = make_insn ~name `MD [30; 9; 10; sh0_4; from'; 3; sh5; 0] in + let x = Word.of_int64 0xAABBCCDD_4242FFAAL in + let y = Word.of_int64 0xFFABCDEF_FFEEAA42L in + let r9 = find_gpr arch "R9" in + let r10 = find_gpr arch "R10" in + let init = Bil.[ + r9 := int x; + r10 := int y; + ] in + let shifted = circ_shift64 x sh in + let mask = mask64 from (63 - sh) in + let expected = Word.((shifted land mask) lor (y land (lnot mask))) in + check_gpr init bytes r10 expected arch ctxt + +let suite = "rotate" >::: [ + "rlwinm sh:3 from:5 to:10" >:: rlwinm `ppc ~sh:3 ~from:5 ~to_:10; + "rlwinm sh:3 from:10 to:5" >:: rlwinm `ppc ~sh:3 ~from:10 ~to_:5; + "rlwinm sh:3 from:0 to:5" >:: rlwinm `ppc ~sh:3 ~from:0 ~to_:5; + "rlwinm sh:3 from:5 to:0" >:: rlwinm `ppc ~sh:3 ~from:5 ~to_:0; + "rlwinm sh:3 from:0 to:0" >:: rlwinm `ppc ~sh:3 ~from:0 ~to_:0; + "rlwinm sh:3 from:0 to:0" >:: rlwinm `ppc ~sh:3 ~from:0 ~to_:0; + "rlwinm sh:0 from:3 to:5" >:: rlwinm `ppc ~sh:0 ~from:3 ~to_:5; + + "rlwnm sh:3 from:5 to:10" >:: rlwnm `ppc ~sh:3 ~from:5 ~to_:10; + "rlwnm sh:3 from:10 to:5" >:: rlwnm `ppc ~sh:3 ~from:10 ~to_:5; + "rlwnm sh:3 from:0 to:5" >:: rlwnm `ppc ~sh:3 ~from:0 ~to_:5; + "rlwnm sh:3 from:5 to:0" >:: rlwnm `ppc ~sh:3 ~from:5 ~to_:0; + "rlwnm sh:3 from:0 to:0" >:: rlwnm `ppc ~sh:3 ~from:0 ~to_:0; + "rlwnm sh:3 from:0 to:0" >:: rlwnm `ppc ~sh:3 ~from:0 ~to_:0; + "rlwnm sh:0 from:3 to:5" >:: rlwnm `ppc ~sh:0 ~from:3 ~to_:5; + + "rlwimi sh:3 from:5 to:10" >:: rlwimi `ppc ~sh:3 ~from:5 ~to_:10; + "rlwimi sh:3 from:10 to:5" >:: rlwimi `ppc ~sh:3 ~from:10 ~to_:5; + "rlwimi sh:3 from:0 to:5" >:: rlwimi `ppc ~sh:3 ~from:0 ~to_:5; + "rlwimi sh:3 from:5 to:0" >:: rlwimi `ppc ~sh:3 ~from:5 ~to_:0; + "rlwimi sh:3 from:0 to:0" >:: rlwimi `ppc ~sh:3 ~from:0 ~to_:0; + "rlwimi sh:3 from:0 to:0" >:: rlwimi `ppc ~sh:3 ~from:0 ~to_:0; + "rlwimi sh:0 from:3 to:5" >:: rlwimi `ppc ~sh:0 ~from:3 ~to_:5; + + "rlwinm ppc64 sh:3 from:5 to:10" >:: rlwinm `ppc64 ~sh:3 ~from:5 ~to_:10; + "rlwinm ppc64 sh:3 from:10 to:5" >:: rlwinm `ppc64 ~sh:3 ~from:10 ~to_:5; + "rlwinm ppc64 sh:3 from:0 to:5" >:: rlwinm `ppc64 ~sh:3 ~from:0 ~to_:5; + "rlwinm ppc64 sh:3 from:5 to:0" >:: rlwinm `ppc64 ~sh:3 ~from:5 ~to_:0; + "rlwinm ppc64 sh:3 from:0 to:0" >:: rlwinm `ppc64 ~sh:3 ~from:0 ~to_:0; + "rlwinm ppc64 sh:3 from:0 to:0" >:: rlwinm `ppc64 ~sh:3 ~from:0 ~to_:0; + "rlwinm ppc64 sh:0 from:3 to:5" >:: rlwinm `ppc64 ~sh:0 ~from:3 ~to_:5; + + "rlwnm ppc64 sh:3 from:5 to:10" >:: rlwnm `ppc64 ~sh:3 ~from:5 ~to_:10; + "rlwnm ppc64 sh:3 from:10 to:5" >:: rlwnm `ppc64 ~sh:3 ~from:10 ~to_:5; + "rlwnm ppc64 sh:3 from:0 to:5" >:: rlwnm `ppc64 ~sh:3 ~from:0 ~to_:5; + "rlwnm ppc64 sh:3 from:5 to:0" >:: rlwnm `ppc64 ~sh:3 ~from:5 ~to_:0; + "rlwnm ppc64 sh:3 from:0 to:0" >:: rlwnm `ppc64 ~sh:3 ~from:0 ~to_:0; + "rlwnm ppc64 sh:3 from:0 to:0" >:: rlwnm `ppc64 ~sh:3 ~from:0 ~to_:0; + "rlwnm ppc64 sh:0 from:3 to:5" >:: rlwnm `ppc64 ~sh:0 ~from:3 ~to_:5; + + "rlwimi ppc64 sh:3 from:5 to:10" >:: rlwimi `ppc64 ~sh:3 ~from:5 ~to_:10; + "rlwimi ppc64 sh:3 from:10 to:5" >:: rlwimi `ppc64 ~sh:3 ~from:10 ~to_:5; + "rlwimi ppc64 sh:3 from:0 to:5" >:: rlwimi `ppc64 ~sh:3 ~from:0 ~to_:5; + "rlwimi ppc64 sh:3 from:5 to:0" >:: rlwimi `ppc64 ~sh:3 ~from:5 ~to_:0; + "rlwimi ppc64 sh:3 from:0 to:0" >:: rlwimi `ppc64 ~sh:3 ~from:0 ~to_:0; + "rlwimi ppc64 sh:3 from:0 to:0" >:: rlwimi `ppc64 ~sh:3 ~from:0 ~to_:0; + "rlwimi ppc64 sh:0 from:3 to:5" >:: rlwimi `ppc64 ~sh:0 ~from:3 ~to_:5; + + "rldicl ppc64 sh:4 from:25" >:: rldicl ~sh:4 ~from:25; + "rldicl ppc64 sh:4 from:55" >:: rldicl ~sh:4 ~from:55; + "rldicl ppc64 sh:4 from:0" >:: rldicl ~sh:4 ~from:0; + "rldicl ppc64 sh:0 from:25" >:: rldicl ~sh:0 ~from:25; + "rldicl ppc64 sh:0 from:0" >:: rldicl ~sh:0 ~from:0; + + "rldicr ppc64 sh:4 to:25" >:: rldicr ~sh:4 ~to_:25; + "rldicr ppc64 sh:4 to:55" >:: rldicr ~sh:4 ~to_:55; + "rldicr ppc64 sh:4 to:0" >:: rldicr ~sh:4 ~to_:0; + "rldicr ppc64 sh:0 to:25" >:: rldicr ~sh:0 ~to_:25; + "rldicr ppc64 sh:0 to:0" >:: rldicr ~sh:0 ~to_:0; + + "rldic ppc64 sh:4 from:25" >:: rldic ~sh:4 ~from:25; + "rldic ppc64 sh:4 from:55" >:: rldic ~sh:4 ~from:55; + "rldic ppc64 sh:4 from:0" >:: rldic ~sh:4 ~from:0; + "rldic ppc64 sh:0 from:25" >:: rldic ~sh:0 ~from:25; + "rldic ppc64 sh:0 from:0" >:: rldic ~sh:0 ~from:0; + + "rldcl ppc64 sh:4 from:25" >:: rldcl ~sh:4 ~from:25; + "rldcl ppc64 sh:4 from:55" >:: rldcl ~sh:4 ~from:55; + "rldcl ppc64 sh:4 from:0" >:: rldcl ~sh:4 ~from:0; + "rldcl ppc64 sh:0 from:25" >:: rldcl ~sh:0 ~from:25; + "rldcl ppc64 sh:0 from:0" >:: rldcl ~sh:0 ~from:0; + + "rldcr ppc64 sh:4 to:25" >:: rldcr ~sh:4 ~to_:25; + "rldcr ppc64 sh:4 to:55" >:: rldcr ~sh:4 ~to_:55; + "rldcr ppc64 sh:4 to:0" >:: rldcr ~sh:4 ~to_:0; + "rldcr ppc64 sh:0 to:25" >:: rldcr ~sh:0 ~to_:25; + "rldcr ppc64 sh:0 to:0" >:: rldcr ~sh:0 ~to_:0; + + "rldimi ppc64 sh:4 from:25" >:: rldimi ~sh:4 ~from:25; + "rldimi ppc64 sh:4 from:55" >:: rldimi ~sh:4 ~from:55; + "rldimi ppc64 sh:4 from:0" >:: rldimi ~sh:4 ~from:0; + "rldimi ppc64 sh:0 from:25" >:: rldimi ~sh:0 ~from:25; + "rldimi ppc64 sh:0 from:0" >:: rldimi ~sh:0 ~from:0; + + + ] diff --git a/lib_test/powerpc/powerpc_shift_tests.ml b/lib_test/powerpc/powerpc_shift_tests.ml new file mode 100644 index 000000000..d4a597425 --- /dev/null +++ b/lib_test/powerpc/powerpc_shift_tests.ml @@ -0,0 +1,276 @@ +open Core_kernel.Std +open OUnit2 +open Bap.Std + +open Powerpc_tests_helpers + +let slw arch sh ctxt = + let name = "SLW" in + let bytes = make_insn ~name `X [31; 9; 10; 11; 24; 0] in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xFFEEAA42_AABBCCDDL in + let shw = Word.of_int ~width sh in + let r9 = find_gpr arch "R9" in + let r10 = find_gpr arch "R10" in + let r11 = find_gpr arch "R11" in + let init = Bil.[ + r9 := int x; + r11 := int shw; + ] in + if sh >= 32 then + check_gpr init bytes r10 (Word.zero width) arch ctxt + else + let x = Word.extract_exn ~hi:31 Word.(x lsl shw) in + let expected = match arch with + | `ppc -> x + | _ -> Word.concat (Word.zero 32) x in + check_gpr init bytes r10 expected arch ctxt + +let srw arch sh ctxt = + let name = "SRW" in + let bytes = make_insn ~name `X [31; 9; 10; 11; 536; 0] in + let width = arch_width arch in + let x = Word.of_int64 ~width 0xFFEEAA42_AABBCCDDL in + let shw = Word.of_int ~width sh in + let r9 = find_gpr arch "R9" in + let r10 = find_gpr arch "R10" in + let r11 = find_gpr arch "R11" in + let init = Bil.[ + r9 := int x; + r11 := int shw; + ] in + if sh >= 32 then + check_gpr init bytes r10 (Word.zero width) arch ctxt + else + let x = Word.((extract_exn ~hi:31 x) lsr shw) in + let expected = match arch with + | `ppc -> x + | _ -> Word.concat (Word.zero 32) x in + check_gpr init bytes r10 expected arch ctxt + +let srawi arch sh x ?(carry=false) ctxt = + let name = "SRAWI" in + let bytes = make_insn ~name `X [31; 9; 10; sh; 824; 0] in + let width = arch_width arch in + let x = Word.of_int64 ~width x in + let shw = Word.of_int ~width sh in + let r9 = find_gpr arch "R9" in + let r10 = find_gpr arch "R10" in + let init = Bil.[ + r9 := int x; + ] in + let left_bits_num = match arch with + | `ppc -> sh + | _ -> 32 + sh in + let left_bits = + if Word.(equal (extract_exn ~hi:31 ~lo:31 x) b1) then + Word.ones left_bits_num + else + Word.zero left_bits_num in + let right_bits_num = width - left_bits_num in + let y = Word.extract_exn ~hi:(right_bits_num - 1) Word.(x lsr shw) in + let expected = Word.concat left_bits y in + let ca_expected = if carry then Word.b1 else Word.b0 in + let ctxt = eval init bytes arch in + let value = lookup_var ctxt r10 in + let ca_val = lookup_var ctxt ca in + let ca32_val = lookup_var ctxt ca32 in + assert_bool "srawi failed: result" (is_equal_words expected value); + assert_bool "srawi failed: ca" (is_equal_words ca_expected ca_val); + assert_bool "srawi failed: ca32" (is_equal_words ca_expected ca32_val) + +let sraw arch sh x ?(carry=false) ctxt = + let name = "SRAW" in + let bytes = make_insn ~name `X [31; 9; 10; 11; 792; 0] in + let width = arch_width arch in + let x = Word.of_int64 ~width x in + let shw = Word.of_int ~width sh in + let r9 = find_gpr arch "R9" in + let r10 = find_gpr arch "R10" in + let r11 = find_gpr arch "R11" in + let init = Bil.[ + r9 := int x; + r11 := int shw; + ] in + let left_bits_num = match arch with + | `ppc -> sh + | _ -> 32 + sh in + let left_bits_num = min left_bits_num width in + let left_bits = + if Word.(equal (extract_exn ~hi:31 ~lo:31 x) b1) then + Word.ones left_bits_num + else + Word.zero left_bits_num in + let right_bits_num = width - left_bits_num in + let expected = + if right_bits_num = 0 then left_bits + else + let right_bits = + Word.extract_exn ~hi:(right_bits_num - 1) Word.(x lsr shw) in + Word.concat left_bits right_bits in + let ca_expected = if carry then Word.b1 else Word.b0 in + let ctxt = eval init bytes arch in + let value = lookup_var ctxt r10 in + let ca_val = lookup_var ctxt ca in + let ca32_val = lookup_var ctxt ca32 in + assert_bool "sraw failed: ca" (is_equal_words ca_expected ca_val); + assert_bool "sraw failed: ca32" (is_equal_words ca_expected ca32_val); + assert_bool "sraw failed: result" (is_equal_words expected value) + +let sld sh x ctxt = + let arch = `ppc64 in + let name = "SLD" in + let bytes = make_insn ~name `X [31; 9; 10; 11; 27; 0] in + let x = Word.of_int64 x in + let shw = Word.of_int ~width:64 sh in + let r9 = find_gpr arch "R9" in + let r10 = find_gpr arch "R10" in + let r11 = find_gpr arch "R11" in + let init = Bil.[ + r9 := int x; + r11 := int shw; + ] in + let expected = Word.(x lsl shw) in + check_gpr init bytes r10 expected arch ctxt + +let srd sh x ctxt = + let arch = `ppc64 in + let name = "SRD" in + let bytes = make_insn ~name `X [31; 9; 10; 11; 539; 0] in + let x = Word.of_int64 x in + let shw = Word.of_int ~width:64 sh in + let r9 = find_gpr arch "R9" in + let r10 = find_gpr arch "R10" in + let r11 = find_gpr arch "R11" in + let init = Bil.[ + r9 := int x; + r11 := int shw; + ] in + let expected = Word.(x lsr shw) in + check_gpr init bytes r10 expected arch ctxt + +let extract_from_int hi lo v = + let w = Word.of_int ~width:32 v in + let w'= Word.extract_exn ~hi ~lo w in + Word.to_int_exn w' + +let sradi sh x ?(carry=false) ctxt = + let arch = `ppc64 in + let name = "SRADI" in + let sh0_4 = extract_from_int 4 0 sh in + let sh5 = extract_from_int 5 5 sh in + let bytes = make_insn ~name `XS [31; 9; 10; sh0_4; 413; sh5; 0] in + let x = Word.of_int64 x in + let shw = Word.of_int ~width:64 sh in + let r9 = find_gpr arch "R9" in + let r10 = find_gpr arch "R10" in + let init = Bil.[ + r9 := int x; + ] in + let expected = + let mask = + if Word.(equal (extract_exn ~hi:63 ~lo:63 x) b1) then + Word.ones 64 + else Word.zero 64 in + let y = Word.(x lsr shw) in + let shm = Word.of_int ~width:64 (64 - sh) in + Word.( (mask lsl shm) lor y) in + let ca_expected = if carry then Word.b1 else Word.b0 in + let ctxt = eval init bytes arch in + let value = lookup_var ctxt r10 in + let ca_val = lookup_var ctxt ca in + let ca32_val = lookup_var ctxt ca32 in + assert_bool "sradi failed: result" (is_equal_words expected value); + assert_bool "sradi failed: ca" (is_equal_words ca_expected ca_val); + assert_bool "sradi failed: ca32" (is_equal_words ca_expected ca32_val) + +let srad sh x ?(carry=false) ctxt = + let arch = `ppc64 in + let name = "SRAD" in + let bytes = make_insn ~name `X [31; 9; 10; 11; 794; 0] in + let x = Word.of_int64 x in + let shw = Word.of_int ~width:64 sh in + let r9 = find_gpr arch "R9" in + let r10 = find_gpr arch "R10" in + let r11 = find_gpr arch "R11" in + let init = Bil.[ + r9 := int x; + r11 := int shw; + ] in + let expected = + let mask = + if Word.(equal (extract_exn ~hi:63 ~lo:63 x) b1) then + Word.ones 64 + else Word.zero 64 in + let y = Word.(x lsr shw) in + let shm = Word.of_int ~width:64 (64 - sh) in + Word.( (mask lsl shm) lor y) in + let ca_expected = if carry then Word.b1 else Word.b0 in + let ctxt = eval init bytes arch in + let value = lookup_var ctxt r10 in + let ca_val = lookup_var ctxt ca in + let ca32_val = lookup_var ctxt ca32 in + assert_bool "srad failed: ca" (is_equal_words ca_expected ca_val); + assert_bool "srad failed: ca32" (is_equal_words ca_expected ca32_val); + assert_bool "srad failed: result" (is_equal_words expected value) + +let suite = "shift" >::: [ + "slw 4" >:: slw `ppc 4; + "slw 0" >:: slw `ppc 0; + "slw zero res" >:: slw `ppc 42; + + "srw 4" >:: srw `ppc 4; + "srw 0" >:: srw `ppc 0; + "srw zero res" >:: srw `ppc 42; + + "srawi 4, pos,not ca" >:: srawi `ppc 4 0xFFFFFFFF_0ABBCCDDL; + "srawi 4, pos,not ca" >:: srawi `ppc 4 0xFFFFFFFF_0ABBCCD0L; + "srawi 4, neg,not ca" >:: srawi `ppc 4 0x00000000_8ABBCCD0L; + "srawi 4, neg,ca" >:: srawi `ppc 4 0x00000000_8ABBCCDDL ~carry:true; + + "sraw 4, pos, not ca" >:: sraw `ppc 4 0xFFFFFFFF_0ABBCCDDL; + "sraw 32, pos, not ca" >:: sraw `ppc 32 0xFFFFFFFF_0ABBCCDDL; + "sraw 4, neg, not ca" >:: sraw `ppc 4 0xFFFFFFFF_8ABBCCD0L; + "sraw 42, neg, ca" >:: sraw `ppc 42 0x00000000_80000000L ~carry:true; + "sraw 4, neg, ca" >:: sraw `ppc 4 0xFFFFFFFF_8ABBCCDAL ~carry:true; + + "slw64 4" >:: slw `ppc64 4; + "slw64 0" >:: slw `ppc64 0; + "slw64 zero res" >:: slw `ppc64 42; + + "srw64 4" >:: srw `ppc64 4; + "srw64 0" >:: srw `ppc64 0; + "srw64 zero res" >:: srw `ppc64 42; + + "srawi64 4, pos,not ca" >:: srawi `ppc64 4 0xFFFFFFFF_0ABBCCDDL; + "srawi64 4, pos,not ca" >:: srawi `ppc64 4 0xFFFFFFFF_0ABBCCD0L; + "srawi64 4, neg,not ca" >:: srawi `ppc64 4 0x00000000_8ABBCCD0L; + "srawi64 4, neg,ca" >:: srawi `ppc64 4 0x00000000_8ABBCCDDL ~carry:true; + + "sraw64 4, pos, not ca" >:: sraw `ppc64 4 0xFFFFFFFF_0ABBCCDDL; + "sraw64 32, pos, not ca" >:: sraw `ppc64 32 0xFFFFFFFF_0ABBCCDDL; + "sraw64 4, neg, not ca" >:: sraw `ppc64 4 0xFFFFFFFF_8ABBCCD0L; + "sraw64 42, neg, ca" >:: sraw `ppc64 42 0x00000000_80000000L ~carry:true; + "sraw64 4, neg, ca" >:: sraw `ppc64 4 0xFFFFFFFF_8ABBCCDAL ~carry:true; + + (* "sld64 0" >:: sld 0 0xABCDEF42_0ABBCCDDL; *) + (* "sld64 4" >:: sld 4 0xABCDEF42_0ABBCCDDL; *) + (* "sld64 42" >:: sld 42 0xABCDEF42_0ABBCCDDL; *) + + (* "srd64 0" >:: srd 0 0xABCDEF42_0ABBCCDDL; *) + (* "srd64 4" >:: srd 4 0xABCDEF42_0ABBCCDDL; *) + (* "srd64 42" >:: srd 42 0xABCDEF42_0ABBCCDDL; *) + + (* "sradi64 4, neg,not ca" >:: sradi 4 0x8ABCDE42_AABBCCD0L; *) + (* "sradi64 4, neg, ca" >:: sradi 4 0x8ABCDE42_AABBCCDDL ~carry:true; *) + (* "sradi64 42, neg, ca" >:: sradi 42 0x8ABCDE42_AABBCCDDL ~carry:true; *) + (* "sradi64 4, pos,not ca" >:: sradi 4 0x0ABCDE42_AABBCCDDL; *) + (* "sradi64 42, pos,not ca" >:: sradi 42 0x0ABCDE42_AABBCCDDL; *) + + (* "srad64 4, neg,not ca" >:: srad 4 0x8ABCDE42_AABBCCD0L; *) + (* "srad64 4, neg, ca" >:: srad 4 0x8ABCDE42_AABBCCDDL ~carry:true; *) + (* "srad64 64, neg, ca" >:: srad 64 0x80000000_00000000L ~carry:true; *) + (* "srad64 4, pos,not ca" >:: srad 4 0x0ABCDE42_AABBCCDDL; *) + (* "srad64 42, pos,not ca" >:: srad 42 0x0ABCDE42_AABBCCDDL; *) + + ] diff --git a/lib_test/powerpc/powerpc_store_tests.ml b/lib_test/powerpc/powerpc_store_tests.ml new file mode 100644 index 000000000..d937961fe --- /dev/null +++ b/lib_test/powerpc/powerpc_store_tests.ml @@ -0,0 +1,331 @@ +open Core_kernel.Std +open Bap.Std +open OUnit2 + +open Powerpc_tests_helpers + +let env_of_arch arch = + mem arch, Size.in_bits (Arch.addr_size arch) + +let st name opcode size ~d_addr arch ctxt = + let bytes = make_insn ~name `D [opcode; 9; 28; d_addr] in + let mem, width = env_of_arch arch in + let r9 = find_gpr arch "R9" in + let r28 = find_gpr arch "R28" in + let addr = 0xABCDEF00 in + let ea = Word.of_int ~width (addr + d_addr) in + let data = Word.of_int64 ~width 0xFFFFFFFFABCDEF42L in + let init = Bil.[ + r9 := int data; + r28 := int (Word.of_int ~width addr); + ] in + let bits = Size.in_bits size in + let expected = Word.extract_exn ~hi:(bits - 1) ~lo:0 data in + check_mem init bytes mem ~addr:ea ~size expected arch ctxt + +let stb = st "STB" 38 `r8 +let sth = st "STH" 44 `r16 +let stw = st "STW" 36 `r32 + +let st_zero_reg name opcode size ~d_addr arch ctxt = + let bytes = make_insn ~name `D [opcode; 9; 0; d_addr] in + let mem, width = env_of_arch arch in + let r9 = find_gpr arch "R9" in + let ea = Word.of_int ~width d_addr in + let data = Word.of_int64 ~width 0xFFFFFFFFABCDEF42L in + let init = Bil.[ + r9 := int data; + ] in + let bits = Size.in_bits size in + let expected = Word.extract_exn ~hi:(bits - 1) ~lo:0 data in + check_mem init bytes mem ~addr:ea ~size expected arch ctxt + +let stb_zero_reg = st_zero_reg "STB" 38 `r8 +let sth_zero_reg = st_zero_reg "STH" 44 `r16 +let stw_zero_reg = st_zero_reg "STW" 36 `r32 + +let stx name opt_opcode size arch ctxt = + let bytes = make_insn ~name `X [31; 9; 14; 31; opt_opcode] in + let mem, width = env_of_arch arch in + let r9 = find_gpr arch "R9" in + let r14 = find_gpr arch "R14" in + let r31 = find_gpr arch "R31" in + let x = 0xABCD0000 in + let y = 0x0000EF42 in + let ea = Word.of_int ~width (x + y) in + let data = Word.of_int64 ~width 0xFFFFFFFFABCDEF42L in + let init = Bil.[ + r9 := int data; + r14 := int @@ Word.of_int ~width x; + r31 := int @@ Word.of_int ~width y + ] in + let bits = Size.in_bits size in + let expected = Word.extract_exn ~hi:(bits - 1) ~lo:0 data in + check_mem init bytes mem ~addr:ea ~size expected arch ctxt + +let stbx = stx "STBX" 215 `r8 +let sthx = stx "STHX" 407 `r16 +let stwx = stx "STWX" 151 `r32 + +let stx_zero_reg name opt_opcode size arch ctxt = + let bytes = make_insn ~name `X [31; 9; 0; 31; opt_opcode] in + let mem, width = env_of_arch arch in + let r9 = find_gpr arch "R9" in + let r31 = find_gpr arch "R31" in + let addr = 0xABCD0000 in + let ea = Word.of_int ~width addr in + let data = Word.of_int64 ~width 0xFFFFFFFFABCDEF42L in + let init = Bil.[ + r9 := int data; + r31 := int @@ Word.of_int ~width addr; + ] in + let bits = Size.in_bits size in + let expected = Word.extract_exn ~hi:(bits - 1) ~lo:0 data in + check_mem init bytes mem ~addr:ea ~size expected arch ctxt + +let stbx_zero_reg = stx_zero_reg "STBX" 215 `r8 +let sthx_zero_reg = stx_zero_reg "STHX" 407 `r16 +let stwx_zero_reg = stx_zero_reg "STWX" 151 `r32 + +let stu name opcode size arch ~d_addr ctxt = + let bytes = make_insn ~name `D [opcode; 4; 29; d_addr] in + let mem, width = env_of_arch arch in + let r4 = find_gpr arch "R4" in + let r29 = find_gpr arch "R29" in + let addr = 0xABCDEF01 in + let ea = Word.of_int ~width (addr + d_addr) in + let data = Word.of_int64 ~width 0xFFFFFFFFABCDEF42L in + let init = Bil.[ + r4 := int data; + r29 := int (Word.of_int ~width addr); + ] in + let bits = Size.in_bits size in + let expected = Word.extract_exn ~hi:(bits - 1) ~lo:0 data in + check_mem init bytes mem ~addr:ea ~size expected arch ctxt; + let expected_addr = Word.of_int ~width (addr + d_addr) in + check_gpr init bytes r29 expected_addr arch ctxt + +let stbu = stu "STBU" 39 `r8 +let sthu = stu "STHU" 45 `r16 +let stwu = stu "STWU" 37 `r32 + +let stux name opt_opcode size arch ctxt = + let bytes = make_insn ~name `X [31; 9; 31; 25; opt_opcode] in + let mem, width = env_of_arch arch in + let r9 = find_gpr arch "R9" in + let r25 = find_gpr arch "R25" in + let r31 = find_gpr arch "R31" in + let x = 0xABCD0000 in + let y = 0x0000EF42 in + let ea = Word.of_int ~width (x + y) in + let data = Word.of_int64 ~width 0xFFFFFFFFABCDEF42L in + let init = Bil.[ + r31 := int (Word.of_int ~width x); + r25 := int (Word.of_int ~width y); + r9 := int data; + ] in + let bits = Size.in_bits size in + let expected = Word.extract_exn ~hi:(bits - 1) ~lo:0 data in + check_mem init bytes mem ~addr:ea ~size expected arch ctxt; + let expected_addr = Word.of_int ~width 0xABCDEF42 in + check_gpr init bytes r31 expected_addr arch ctxt + +let stbux = stux "STBUX" 247 `r8 +let sthux = stux "STHUX" 439 `r16 +let stwux = stux "STWUX" 183 `r32 + +let std ctxt = + let arch = `ppc64 in + let bytes = "\xf8\x29\x00\x08" in (** std r1, 8(r9) *) + let mem, width = env_of_arch arch in + let r1 = find_gpr arch "R1" in + let r9 = find_gpr arch "R9" in + let addr = 0xABCDEF44 in + let disp = 8 in + let ea = Word.of_int ~width (addr + disp) in + let data = Word.of_int64 ~width 0xCCABDD42_ABCDEF42L in + let init = Bil.[ + r9 := int (Word.of_int ~width:64 addr); + r1 := int data; + ] in + let expected = data in + check_mem init bytes mem ~addr:ea ~size:`r64 expected arch ctxt + +let stdx ctxt = + let arch = `ppc64 in + let bytes = "\x7c\x28\x49\x2a" in (** stdx r1, r8, r9 *) + let mem, width = env_of_arch arch in + let r1 = find_gpr arch "R1" in + let r8 = find_gpr arch "R8" in + let r9 = find_gpr arch "R9" in + let x = 0xABCD0000 in + let y = 0x0000EF42 in + let ea = Word.of_int ~width (x + y) in + let data = Word.of_int64 0xCCABDD42_ABCDEF42L in + let init = Bil.[ + r1 := int data; + r8 := int @@ Word.of_int ~width:64 x; + r9 := int @@ Word.of_int ~width:64 y; + ] in + let expected = data in + check_mem init bytes mem ~addr:ea ~size:`r64 expected arch ctxt + +let stdu ctxt = + let arch = `ppc64 in + let bytes = "\xf8\x29\x00\x09" in (** stdu r1, 8(r9) *) + let mem, width = env_of_arch arch in + let r1 = find_gpr arch "R1" in + let r9 = find_gpr arch "R9" in + let addr = 0xABCDEF42 in + let disp = 8 in + let ea = Word.of_int ~width (addr + disp) in + let data = Word.of_int64 0xCCABDD42_ABCDEF42L in + let init = Bil.[ + r9 := int (Word.of_int ~width:64 addr); + r1 := int data; + ] in + let expected = data in + check_mem init bytes mem ~addr:ea ~size:`r64 expected arch ctxt; + let expected_addr = Word.of_int ~width:64 (addr + disp) in + check_gpr init bytes r9 expected_addr arch ctxt + +let stdux ctxt = + let arch = `ppc64 in + let bytes = "\x7c\x28\x49\x6a" in (** stdux r1, r8, r9 *) + let mem, width = env_of_arch arch in + let r1 = find_gpr arch "R1" in + let r8 = find_gpr arch "R8" in + let r9 = find_gpr arch "R9" in + let x = 0xABCD0000 in + let y = 0x0000EF42 in + let ea = Word.of_int ~width (x + y) in + let data = Word.of_int64 0xCCABDD42_ABCDEF42L in + let init = Bil.[ + r1 := int data; + r8 := int (Word.of_int ~width:64 x); + r9 := int (Word.of_int ~width:64 y); + ] in + let expected = data in + check_mem init bytes mem ~addr:ea ~size:`r64 expected arch ctxt; + let expected_addr = Word.of_int ~width:64 0xABCDEF42 in + check_gpr init bytes r8 expected_addr arch ctxt + +let stdux_big_addr ctxt = + let bytes = "\x7c\x28\x49\x6a" in (** stdux r1, r8, r9 *) + let mem, _width = env_of_arch `ppc64 in + let r1 = find_gpr `ppc64 "R1" in + let r8 = find_gpr `ppc64 "R8" in + let r9 = find_gpr `ppc64 "R9" in + let x = Word.of_int64 0xCABCEF42_ABCD0000L in + let y = Word.of_int64 0x0000EF42L in + let ea = Word.(x + y) in + let data = Word.of_int64 0xCCABDD42_ABCDEF42L in + let init = Bil.[ + r1 := int data; + r8 := int x; + r9 := int y; + ] in + let expected = data in + check_mem init bytes mem ~addr:ea ~size:`r64 expected `ppc64 ctxt; + let expected_addr = ea in + check_gpr init bytes r8 expected_addr `ppc64 ctxt + +let stbrx name opt_opcode size arch ctxt = + let bytes = make_insn ~name `X [31; 1; 2; 3; opt_opcode; 0] in + let mem, width = env_of_arch arch in + let r1 = find_gpr arch "R1" in + let r2 = find_gpr arch "R2" in + let r3 = find_gpr arch "R3" in + let addr = 0xABCDEF00 in + let disp = 0x42 in + let ea = Word.of_int ~width (addr + disp) in + let data = Word.of_int64 ~width 0xCCABDD42_ABCDEF42L in + let init = Bil.[ + r1 := int data; + r2 := int (Word.of_int ~width addr); + r3 := int (Word.of_int ~width disp); + ] in + let expected = + Seq.to_list_rev (Word.enum_bytes data BigEndian) |> + List.fold ~init:None ~f:(fun acc b -> + match acc with + | None -> Some b + | Some p -> Some (Word.concat p b)) |> + Option.value_exn |> + Word.extract_exn ~hi:(width -1) ~lo:(width - Size.in_bits size) in + check_mem init bytes mem ~addr:ea ~size expected arch ctxt + +let sthbrx = stbrx "STHBRX" 918 `r16 +let stwbrx = stbrx "STWBRX" 662 `r32 +let stdbrx = stbrx "STDBRX" 660 `r64 `ppc64 + +let suite = "store" >::: [ + "stb32 +imm" >:: stb `ppc ~d_addr:16; + "stb32 -imm" >:: stb `ppc ~d_addr:(-16); + "stb32 0reg" >:: stb_zero_reg `ppc ~d_addr:16; + "sth32 +imm" >:: sth `ppc ~d_addr:16; + "sth32 -imm" >:: sth `ppc ~d_addr:(-16); + "sth32 0reg" >:: sth_zero_reg `ppc ~d_addr:16; + "stw32 +imm" >:: stw `ppc ~d_addr:16; + "stw32 -imm" >:: stw `ppc ~d_addr:(-16); + "stw32 0reg" >:: stw_zero_reg `ppc ~d_addr:16; + + "stbx32" >:: stbx `ppc; + "stbx32 0reg" >:: stbx_zero_reg `ppc; + "sthx32" >:: sthx `ppc; + "sthx32 0reg" >:: sthx_zero_reg `ppc; + "stwx32" >:: stwx `ppc; + "stwx32 0reg" >:: stwx_zero_reg `ppc; + + "stbu32 +imm" >:: stbu `ppc ~d_addr:16; + "stbu32 -imm" >:: stbu `ppc ~d_addr:(-16); + "sthu32 +imm" >:: sthu `ppc ~d_addr:16; + "sthu32 -imm" >:: sthu `ppc ~d_addr:(-16); + "stwu32 +imm" >:: stwu `ppc ~d_addr:16; + "stwu32 -imm" >:: stwu `ppc ~d_addr:(-16); + + "stbux32" >:: stbux `ppc; + "sthux32" >:: sthux `ppc; + "stwux32" >:: stwux `ppc; + + "sthbrx32" >:: sthbrx `ppc; + "stwbrx32" >:: stwbrx `ppc; + + "stb64 +imm" >:: stb `ppc64 ~d_addr:16; + "stb64 -imm" >:: stb `ppc64 ~d_addr:(-16); + "stb64 0reg" >:: stb_zero_reg `ppc64 ~d_addr:16; + "sth64 +imm" >:: sth `ppc64 ~d_addr:16; + "sth64 -imm" >:: sth `ppc64 ~d_addr:(-16); + "sth64 0reg" >:: sth_zero_reg `ppc64 ~d_addr:16; + "stw64 +imm" >:: stw `ppc64 ~d_addr:16; + "stw64 -imm" >:: stw `ppc64 ~d_addr:(-16); + "stw64 0reg" >:: stw_zero_reg `ppc64 ~d_addr:16; + + "stbx64" >:: stbx `ppc64; + "stbx64 0reg" >:: stbx_zero_reg `ppc64; + "sthx64" >:: sthx `ppc64; + "sthx64 0reg" >:: sthx_zero_reg `ppc64; + "stwx64" >:: stwx `ppc64; + "stwx64 0reg" >:: stwx_zero_reg `ppc64; + + "stbu64 +imm" >:: stbu `ppc64 ~d_addr:16; + "stbu64 -imm" >:: stbu `ppc64 ~d_addr:(-16); + "sthu64 +imm" >:: sthu `ppc64 ~d_addr:16; + "sthu64 -imm" >:: sthu `ppc64 ~d_addr:(-16); + "stwu64 +imm" >:: stwu `ppc64 ~d_addr:16; + "stwu64 -imm" >:: stwu `ppc64 ~d_addr:(-16); + + "stbux64" >:: stbux `ppc64; + "sthux64" >:: sthux `ppc64; + "stwux64" >:: stwux `ppc64; + + "std64" >:: std; + "stdx64" >:: stdx; + "stdu64" >:: stdu; + "stdux64" >:: stdux; + "stdux64a" >:: stdux_big_addr; + + "sthbrx64" >:: sthbrx `ppc64; + "stwbrx64" >:: stwbrx `ppc64; + "stdbrx64" >:: stdbrx; + ] diff --git a/lib_test/powerpc/powerpc_tests_helpers.ml b/lib_test/powerpc/powerpc_tests_helpers.ml new file mode 100644 index 000000000..eb2f7c2dc --- /dev/null +++ b/lib_test/powerpc/powerpc_tests_helpers.ml @@ -0,0 +1,491 @@ +open Core_kernel.Std +open Bap.Std +open OUnit2 + +module Dis = Disasm_expert.Basic + +module type Bitwidth = sig + val gpr_bitwidth : int + val addr_size : addr_size +end + +let range32 = List.range 0 32 +let make_name prefix i = sprintf "%s%d" prefix i +let make_var_i typ prefix i = Var.create (make_name prefix i) typ + +let make_regs typ ?alias prefix range = + List.fold ~init:String.Map.empty ~f:(fun regs i -> + let var = make_var_i typ prefix i in + let name = Var.name var in + let regs = Map.add regs name var in + match alias with + | None -> regs + | Some a -> + let name = make_name a i in + Map.add regs name var) range + +let flag name = Var.create name (Type.imm 1) + +module Make(B : Bitwidth) = struct + open B + let gpr = make_regs (Type.imm gpr_bitwidth) "R" ~alias:"X" range32 + let ctr = Var.create "CTR" (Type.imm gpr_bitwidth) + let lr = Var.create "LR" (Type.imm gpr_bitwidth) + let tar = Var.create "TAR" (Type.imm gpr_bitwidth) + + (** condition register bits *) + let cr0 = flag "CR7UN" + let cr1 = flag "CR7EQ" + let cr2 = flag "CR7GT" + let cr3 = flag "CR7LT" + let cr4 = flag "CR6UN" + let cr5 = flag "CR6EQ" + let cr6 = flag "CR6GT" + let cr7 = flag "CR6LT" + let cr8 = flag "CR5UN" + let cr9 = flag "CR5EQ" + let cr10 = flag "CR5GT" + let cr11 = flag "CR5LT" + let cr12 = flag "CR4UN" + let cr13 = flag "CR4EQ" + let cr14 = flag "CR4GT" + let cr15 = flag "CR4LT" + let cr16 = flag "CR3UN" + let cr17 = flag "CR3EQ" + let cr18 = flag "CR3GT" + let cr19 = flag "CR3LT" + let cr20 = flag "CR2UN" + let cr21 = flag "CR2EQ" + let cr22 = flag "CR2GT" + let cr23 = flag "CR2LT" + let cr24 = flag "CR1UN" + let cr25 = flag "CR1EQ" + let cr26 = flag "CR1GT" + let cr27 = flag "CR1LT" + let cr28 = flag "CR0UN" + let cr29 = flag "CR0EQ" + let cr30 = flag "CR0GT" + let cr31 = flag "CR0LT" + + let cr_bits = [ + cr0; cr1; cr2; cr3; cr4; cr5; cr6; cr7; + cr8; cr9; cr10; cr11; cr12; cr13; cr14; cr15; + cr16; cr17; cr18; cr19; cr20; cr21; cr22; cr23; + cr24; cr25; cr26; cr27; cr28; cr29; cr30; cr31; + ] + + let cri = + let _, bits = + List.fold (List.rev cr_bits) ~init:(0,Int.Map.empty) + ~f:(fun (num, bits) bit -> + num + 1, Map.add bits ~key:num ~data:bit) in + bits + + let crn = + Int.Map.fold cri ~init:String.Map.empty + ~f:(fun ~key:_ ~data:var acc -> + Map.add acc (Var.name var) var) + + let fields = [ + "CR0", 0, (cr28, cr29, cr30, cr31); + "CR1", 1, (cr24, cr25, cr26, cr27); + "CR2", 2, (cr20, cr21, cr22, cr23); + "CR3", 3, (cr16, cr17, cr18, cr19); + "CR4", 4, (cr12, cr13, cr14, cr15); + "CR5", 5, (cr8, cr9, cr10, cr11); + "CR6", 6, (cr4, cr5, cr6, cr7); + "CR7", 7, (cr0, cr1, cr2, cr3); + ] + + let cr_fields = + List.fold fields ~init:String.Map.empty ~f:(fun fs (name, _, fd) -> + Map.add fs name fd) + + let cri_fields = + List.fold fields ~init:Int.Map.empty ~f:(fun fs (_, index, fd) -> + Map.add fs index fd) + + (** fixed precision flags *) + let so = flag "SO" (** summary overflow *) + let ca = flag "CA" + let ov = flag "OV" + let ca32 = flag "CA32" (** carry of low-order 32 bit result *) + let ov32 = flag "OV32" (** overflow of low-order 32 bit result *) + let mem = Var.create "mem" (Type.mem addr_size `r8) +end + + +module P32 = Make(struct + let gpr_bitwidth = 32 + let addr_size = `r32 + end) + +module P64 = Make(struct + let gpr_bitwidth = 64 + let addr_size = `r64 + end) + +module Any_ppc = P32 + +let raise_arch () = + failwith "powerpc arch is the only expected" + +let cr_bit n = + Int.Map.find_exn Any_ppc.cri n + +let nf = cr_bit 0 +let pf = cr_bit 1 +let zf = cr_bit 2 +let ca = Any_ppc.ca +let ca32 = Any_ppc.ca32 + +let lr = function + | `ppc -> P32.lr + | `ppc64 -> P64.lr + | _ -> raise_arch () + +let ctr = function + | `ppc -> P32.ctr + | `ppc64 -> P64.ctr + | _ -> raise_arch () + +let tar = function + | `ppc -> P32.tar + | `ppc64 -> P64.tar + | _ -> raise_arch () + +let cri = Any_ppc.cri + +let mem = function + | `ppc -> P32.mem + | `ppc64 -> P64.mem + | _ -> raise_arch () + +module E = struct + + let cr = + match List.rev P32.cr_bits with + | [] -> assert false + | v :: vars -> + List.fold vars ~init:(Bil.var v) ~f:(fun e v -> Bil.(e ^ var v)) + + let cri = Map.map cri ~f:(fun v -> Bil.var v) +end + + +let create_dis arch = + Dis.create ~backend:"llvm" (Arch.to_string arch) |> + Or_error.ok_exn |> + Dis.store_kinds |> + Dis.store_asm + +let create_memory arch s addr = + let endian = Arch.endian arch in + Memory.create endian addr @@ + Bigstring.of_string s |> function + | Ok r -> r + | Error _ -> failwith "can't create memory" + +let to_bil arch mem insn = + let module T = (val (target_of_arch arch)) in + T.lift mem insn + +let get_insn ?addr arch bytes = + let width = Arch.addr_size arch |> Size.in_bits in + let addr = match addr with + | None -> Addr.of_int ~width 0 + | Some a -> a in + let mem = create_memory arch bytes addr in + let dis = create_dis arch in + match Dis.insn_of_mem dis mem with + | Ok (mem, Some insn, _) -> + let insn_name = Insn.(name @@ of_basic insn) in + mem, insn, insn_name + | _ -> failwith "disasm failed" + +let lookup_var c var = match c#lookup var with + | None -> None + | Some r -> + match Bil.Result.value r with + | Bil.Imm word -> Some word + | Bil.Bot | Bil.Mem _ -> None + +let find_gpr arch name = + try + match arch with + | `ppc -> String.Map.find_exn P32.gpr name + | _ -> String.Map.find_exn P64.gpr name + with _ -> + sprintf "gpr %s not" name |> failwith + +let get_bil ?addr arch bytes = + let mem,insn,_ = get_insn ?addr arch bytes in + to_bil arch mem insn + +let check_bil bil = + match Type.check bil with + | Error te -> + let err = + sprintf "The lifted code is not well-typed: %s" + (Type.Error.to_string te) in + failwith err + | Ok () -> () + +(** [check_gpr ?addr init_bil bytes var expected arch ctxt] - + tests if a result bound to the [var] is equal to + [exptected]. Evaluates bil, that is a concatenation + of [init_bil] and code, obtained from lifting [bytes]. + [addr] is an instruction address, 0 by default. *) +let check_gpr ?addr init bytes var expected arch _ctxt = + let mem,insn,insn_name = get_insn ?addr arch bytes in + let bil = Or_error.ok_exn @@ to_bil arch mem insn in + check_bil (init @ bil); + let c = Stmt.eval (init @ bil) (new Bili.context) in + match lookup_var c var with + | None -> assert_bool "var not found OR it's result not Imm" false + | Some w -> + if not (Word.equal w expected) || + (Word.bitwidth w <> Word.bitwidth expected) then + printf "\n%s: check failed for %s: expected %s <> %s\n" + insn_name + (Var.name var) + (Word.to_string expected) + (Word.to_string w); + assert_equal ~cmp:Word.equal w expected + +(** [eval ?addr init_bil bytes arch] - evaluates bil, that is a concatenation + of [init_bil] and code, obtained from lifting [bytes]. + [addr] is an instruction address, 0 by default. *) +let eval ?addr init bytes arch = + let mem,insn,_ = get_insn ?addr arch bytes in + let bil = Or_error.ok_exn @@ to_bil arch mem insn in + check_bil (init @ bil); + Stmt.eval (init @ bil) (new Bili.context) + +let load_word ctxt mem addr endian size = + let bits = Size.in_bits size in + let tmp = Var.create ~fresh:true "tmp" (Type.imm bits) in + let bil = Bil.[ + tmp := load ~mem:(var mem) ~addr:(int addr) endian size; + ] in + check_bil bil; + let ctxt = Stmt.eval bil ctxt in + lookup_var ctxt tmp + +let check_mem init bytes mem ~addr ~size expected ?(endian=BigEndian) arch _ctxt = + let memory,insn,insn_name = get_insn arch bytes in + let bil = Or_error.ok_exn @@ to_bil arch memory insn in + check_bil (init @ bil); + let c = Stmt.eval (init @ bil) (new Bili.context) in + match load_word c mem addr endian size with + | None -> assert_bool "word not found OR it's result not Imm" false + | Some w -> + if not (Word.equal w expected) then + printf "\n%s: check failed for %s: expected %s <> %s\n" + insn_name + (Addr.to_string addr) + (Word.to_string expected) + (Word.to_string w); + assert_equal ~cmp:Word.equal w expected + +let concat_words ws = match ws with + | [] -> failwith "words list is empty!" + | w :: ws -> + List.fold ~init:w ~f:(fun ws w -> Word.concat ws w) ws + +(** [make_bytes ws] - returns a string representation of concated words [ws] *) +let make_bytes ws = + let bytes = concat_words ws in + let bytes = Seq.to_list @@ Word.enum_chars bytes BigEndian in + String.of_char_list bytes + +let is_equal_words w = function + | None -> false + | Some w' -> Word.equal w w' + +let string_of_bytes bytes = + String.fold ~init:"" ~f:(fun acc b -> + sprintf "%s%02X " acc (Char.to_int b)) bytes + +let arch_width a = Arch.addr_size a |> Size.in_bits + +type form = [ + | `B + | `D + | `I + | `M + | `MD + | `MDS + | `VA + | `X + | `XL + | `XFX + | `XO + | `XS +] [@@deriving sexp] + +let make_insn ?name ?(arch=`ppc) form fields = + let b0 = Word.b0 in + let word ~width n = Word.of_int ~width n in + let bytes = + match form, fields with + | `B, [opcode; bo; bi; bd; aa; lk] -> + make_bytes [ + word ~width:6 opcode; + word ~width:5 bo; + word ~width:5 bi; + word ~width:14 bd; + word ~width:1 aa; + word ~width:1 lk; + ] + | `D, [opcode; rt; ra; d] -> + make_bytes [ + word ~width:6 opcode; + word ~width:5 rt; + word ~width:5 ra; + word ~width:16 d; + ] + | `I, [opcode; imm; aa; lk] -> + make_bytes [ + word ~width:6 opcode; + word ~width:24 imm; + word ~width:1 aa; + word ~width:1 lk; + ] + | `M, [opcode; rs; ra; sh; mb; me; rc] -> + make_bytes [ + word ~width:6 opcode; + word ~width:5 rs; + word ~width:5 ra; + word ~width:5 sh; + word ~width:5 mb; + word ~width:5 me; + word ~width:1 rc; + ] + | `MD, [opcode; rs; ra; sh1; me; opt; sh2; rc] -> + make_bytes [ + word ~width:6 opcode; + word ~width:5 rs; + word ~width:5 ra; + word ~width:5 sh1; + word ~width:6 me; + word ~width:3 opt; + word ~width:1 sh2; + word ~width:1 rc; + ] + | `MDS, [opcode; rs; ra; rb; mb; opt; rc] -> + make_bytes [ + word ~width:6 opcode; + word ~width:5 rs; + word ~width:5 ra; + word ~width:5 rb; + word ~width:6 mb; + word ~width:4 opt; + word ~width:1 rc; + ] + | `VA, [opcode; rt; ra; rb; rc; opt_opcode;] -> + make_bytes [ + word ~width:6 opcode; + word ~width:5 rt; + word ~width:5 ra; + word ~width:5 rb; + word ~width:5 rc; + word ~width:6 opt_opcode; + ] + | `X, [opcode; rt; ra; rb; opt_opcode; rc] -> + make_bytes [ + word ~width:6 opcode; + word ~width:5 rt; + word ~width:5 ra; + word ~width:5 rb; + word ~width:10 opt_opcode; + word ~width:1 rc; + ] + | `X, [opcode; rt; ra; rb; opt_opcode;] -> + make_bytes [ + word ~width:6 opcode; + word ~width:5 rt; + word ~width:5 ra; + word ~width:5 rb; + word ~width:10 opt_opcode; + b0; + ] + | `XL, [opcode; bf; x; bfa; y; z; opt_opcode; w;] -> + make_bytes [ + word ~width:6 opcode; + word ~width:3 bf; + word ~width:2 x; + word ~width:3 bfa; + word ~width:2 y; + word ~width:5 z; + word ~width:10 opt_opcode; + word ~width:1 w; + ] + | `XL, [opcode; bt; ba; bb; opt_opcode; x] -> + make_bytes [ + word ~width:6 opcode; + word ~width:5 bt; + word ~width:5 ba; + word ~width:5 bb; + word ~width:10 opt_opcode; + word ~width:1 x; + ] + | `XL, [opcode; bo; bi; empty; bh; opt_opcode; lk;] -> + make_bytes [ + word ~width:6 opcode; + word ~width:5 bo; + word ~width:5 bi; + word ~width:3 empty; + word ~width:2 bh; + word ~width:10 opt_opcode; + word ~width:1 lk; + ] + | `XFX, [opcode; rs; x; data; y; opt_opcode; z] -> + make_bytes [ + word ~width:6 opcode; + word ~width:5 rs; + word ~width:1 x; + word ~width:8 data; + word ~width:1 x; + word ~width:10 opt_opcode; + word ~width:1 z; + ] + | `XFX, [opcode; rs; data; opt_opcode; x] -> + make_bytes [ + word ~width:6 opcode; + word ~width:5 rs; + word ~width:10 data; + word ~width:10 opt_opcode; + word ~width:1 x; + ] + | `XO, [opcode; rt; ra; rb; oe; opt_opcode; rc] -> + make_bytes [ + word ~width:6 opcode; + word ~width:5 rt; + word ~width:5 ra; + word ~width:5 rb; + word ~width:1 oe; + word ~width:9 opt_opcode; + word ~width:1 rc; + ] + | `XS, [opcode; rs; ra; sh1; opt; sh2; rc] -> + make_bytes [ + word ~width:6 opcode; + word ~width:5 rs; + word ~width:5 ra; + word ~width:5 sh1; + word ~width:9 opt; + word ~width:1 sh2; + word ~width:1 rc; + ] + | _ -> failwith "unexpected argument set for given insn form" in + let () = match name with + | None -> () + | Some name -> + let _,_insn,insn_name = get_insn arch bytes in + if not (String.equal name insn_name) then + let err = + sprintf "error: failed to construct %s insn, got a %s" + name insn_name in + failwith err in + bytes diff --git a/lib_test/powerpc/powerpc_tests_helpers.mli b/lib_test/powerpc/powerpc_tests_helpers.mli new file mode 100644 index 000000000..5c13a5fd7 --- /dev/null +++ b/lib_test/powerpc/powerpc_tests_helpers.mli @@ -0,0 +1,91 @@ +open Core_kernel.Std +open Bap.Std +open OUnit2 + +val nf : var +val pf : var +val zf : var +val ca : var +val ca32 : var +val lr : arch -> var +val ctr : arch -> var +val tar : arch -> var +val cri : var Int.Map.t +val mem : arch -> var + +module E : sig + val cr : exp + val cri : exp Int.Map.t +end + + +(** [cr_bit n] - returns a condition register bit [n] *) +val cr_bit : int -> var + +(** [find_gpr arch name] - return a GPR with a [name] *) +val find_gpr : arch -> string -> var + +(** [get_bil ?addr arch bytes] - returns a bil code + from [bytes] for [arch]. [addr] is an instruction address, + 0 by default. *) +val get_bil : ?addr:addr -> arch -> string -> bil Or_error.t + +(** [check_gpr ?addr init_bil bytes var expected arch ctxt] - + tests if a result bound to the [var] is equal to + [exptected]. Evaluates bil, that is a concatenation + of [init_bil] and code, obtained from lifting [bytes]. + [addr] is an instruction address, 0 by default. *) +val check_gpr : ?addr:addr -> bil -> string -> var -> addr -> arch -> test_ctxt -> unit + +(** [eval ?addr init_bil bytes arch] - evaluates bil, that is a concatenation + of [init_bil] and code, obtained from lifting [bytes]. + [addr] is an instruction address, 0 by default. *) +val eval : ?addr:addr -> bil -> string -> arch -> Bili.context + +(** [check_mem init bytes mem ~addr size expected ?endian arch ctxt] - + tests if a word of [size] at [addr] in memory [mem] is equal to [expected]. + Evaluates bil, that is a concatenation of [init_bil] and code, + obtained from lifting [bytes]. *) +val check_mem : bil -> string -> var -> addr:addr -> size:size -> addr -> ?endian:endian -> arch -> test_ctxt -> unit + +(** [lookup_var context var] - returns a word, bound to [var] in [context] *) +val lookup_var : Bili.context -> var -> word option + +(** [make_bytes ws] - return a string of bytes, that obtained from + concatenaion of [ws] *) +val make_bytes : word list -> string + +(** [concat_words ws] - returns a concatenated [ws] *) +val concat_words : word list -> word + +(** [is_equal_words w w'] - return true iff Some w = w' *) +val is_equal_words : word -> word option -> bool + +(** [string_of_bytes bytes] - returns a readable string from [bytes] *) +val string_of_bytes : string -> string + +(** [arch_width arch] - returns addr_size of [arch] in bits *) +val arch_width : arch -> int + +(** PowerPC instruction forms *) +type form = [ + | `B + | `D + | `I + | `M + | `MD + | `MDS + | `VA + | `X + | `XL + | `XFX + | `XO + | `XS +] + +(** [make_insn ~name form fields] - return a bytes sequence from + instruction [form] and [fields] list. Raises is form and fields + mismatches. If [name] is provided, checks that formed bytes + belongs to expected instruction for [arch], raises if not. + Default [arch] is ppc *) +val make_insn : ?name:string -> ?arch:arch -> form -> int list -> string diff --git a/lib_test/powerpc/run_powerpc_tests.ml b/lib_test/powerpc/run_powerpc_tests.ml new file mode 100644 index 000000000..e1faab1d6 --- /dev/null +++ b/lib_test/powerpc/run_powerpc_tests.ml @@ -0,0 +1,29 @@ +open Core_kernel.Std +open OUnit2 +open Bap_plugins.Std + +let suite = "PowerPC" >::: [ + Powerpc_add_tests.suite; + Powerpc_arith_tests.suite; + Powerpc_branch_tests.suite; + Powerpc_compare_tests.suite; + Powerpc_cr_tests.suite; + Powerpc_load_tests.suite; + Powerpc_logical_tests.suite; + Powerpc_move_tests.suite; + Powerpc_rotate_tests.suite; + Powerpc_shift_tests.suite; + Powerpc_store_tests.suite; + ] + +let load_plugins () = + Plugins.load () |> + List.iter ~f:(function + | Ok _ -> () + | Error (p,e)-> + assert_string ("failed to load plugin from " ^ p ^ ": " ^ + Error.to_string_hum e)) + +let () = + load_plugins (); + run_test_tt_main suite diff --git a/oasis/powerpc b/oasis/powerpc index f64ac0c49..6bad594b5 100644 --- a/oasis/powerpc +++ b/oasis/powerpc @@ -32,3 +32,35 @@ Library powerpc_plugin Powerpc_sub, Powerpc_primus_loader XMETAExtraLines: tags="powerpc, lifter" + +Library powerpc_test + Path: lib_test/powerpc + Build$: flag(tests) && (flag(everything) || flag(powerpc)) + CompiledObject: best + BuildDepends: bap, oUnit + Install: false + Modules: Powerpc_add_tests, + Powerpc_arith_tests, + Powerpc_branch_tests, + Powerpc_compare_tests, + Powerpc_cr_tests, + Powerpc_load_tests, + Powerpc_logical_tests, + Powerpc_move_tests, + Powerpc_rotate_tests, + Powerpc_shift_tests, + Powerpc_store_tests, + Powerpc_tests_helpers + +Executable run_powerpc_tests + Path: lib_test/powerpc + Build$: flag(tests) && (flag(everything) || flag(powerpc)) + CompiledObject: best + BuildDepends: bap.plugins, findlib.dynload, oUnit, powerpc_test + Install: false + MainIs: run_powerpc_tests.ml + +Test powerpc_tests + TestTools: run_powerpc_tests + Run$: flag(tests) && (flag(everything) || flag(powerpc)) + Command: $run_powerpc_tests \ No newline at end of file