new file mode 100644
@@ -0,0 +1,744 @@
+#!/usr/bin/perl -w
+#######################################################################
########
+# File: risugen_ppc.pm
+# Date: 4-14-2017
+# Description: Perl module for generating PowerPC instructions with
risugen.
+# Based on Jose Ricardo Ziviani (IBM) - ppc64 implementation
+#######################################################################
########
+
+# risugen -- generate a test binary file for use with risu
+# See 'risugen --help' for usage information.
+package risugen_ppc;
+
+use strict;
+use warnings;
+use bigint;
+use risugen_common;
+
+require Exporter;
+
+our @ISA = qw(Exporter);
+our @EXPORT = qw(write_test_code);
+
+# Has all debug messages printed if set to 1
+my $debug = 0;
+
+# First available slot in the stack
+my $available_stack_slot = 40;
+
+my $OP_COMPARE = 0; # compare registers
+my $OP_TESTEND = 1; # end of test, stop
+
+# prints debugging information if DEBUG is set to 1
+sub debug_print {
+ if ($debug == 1) {
+ my $test = sprintf(shift, @_);
+ print $test;
+ }
+}
+
+# setup the environment for a memory access involving two registers
+# first input: general purpose register rA
+# second input: general purpose register rB
+sub reg_plus_reg($$)
+{
+ my ($rA, $rB) = @_;
+ my $value;
+ my $low_bits;
+ my $high_bits;
+
+ $value = rand();
+
+ # Has to be loaded like this because we can't just load a 32 bit
value
+ $low_bits = $value & 0xffff;
+ $high_bits = $value >> 16;
+
+ # Add a value into the expected memory location
+ write_lis(10, $high_bits); # lis r10, $high_bits
+ write_ori(10, 10, $low_bits); # ori r10, r10, $low_bits
+ write_stw(10, $available_stack_slot); # stw r10,
$available_stack_slot(r1)
+
+ # setup the two registers to find the memory location
+ write_mr($rA, 1); # mr $rA, r1
+ write_li($rB, $available_stack_slot); # li $rB,
$available_stack_slot
+ return $rA;
+}
+
+# Handle register + immediate addressing mode
+# first input: base register
+# second input: immediate value (offset)
+sub reg_plus_imm($$)
+{
+ my ($base_register, $number) = @_;
+
+ # load a random floating point value into memory
+ my $float_value = rand();
+ my $ieee_value = convert_to_IEEE($float_value);
+ my $ieee_high_bits; # the upper 16 bits of $ieee_value
+ my $ieee_low_bits; # the lower 16 bits of $ieee_value
+
+ $ieee_high_bits = $ieee_value >> 16;
+ $ieee_low_bits = $ieee_value & 0xffff;
+ write_lis(10, $ieee_high_bits); # lis r10, $ieee_high_bits
+ write_ori(10, 10, $ieee_low_bits); # ori r10, r10,
$ieee_low_bits
+ write_stw(10, $number); # stw r10, $number(r1)
+ write_mr($base_register, 1); # mr $base_register, r1
+ return $base_register;
+}
+
+# convert float value to IEEE 754
+# input: floating point value (e.g. 1.23)
+# output: IEEE 754 single precision value
+sub convert_to_IEEE($)
+{
+ my $float_value = $_[0];
+ my $ieee_value = unpack "L", pack "f", $float_value;
+ return $ieee_value;
+}
+
+# returns a random double precision IEEE 754 value
+# output: 64 bit number
+sub get_random_IEEE_double_value()
+{
+ my @number_array = (0x40273333333333330, 0x405EDCCCCCCCCCCD,
+ 0x40700A6666666666, 0x412E240CA45A1CAC,
+ 0x407C3E8F5C28F5C3, 0x408DBF189374BC6A);
+ my $size_of_array = scalar @number_array;
+ my $index = int rand($size_of_array);
+ return $number_array[$index];
+}
+
+# writes ppc assembly code to load a IEEE 754 double value
+# input one: general purpose register number
+# input two: immediate value (offset)
+# output: IEEE 754 double value
+sub load_double_float_imm($$)
+{
+ my ($rA, $number) = @_;
+
+ my $ieee_double; # ieee 754 double float value
+ my $ieee_high_bits; # the upper 16 bits of $ieee_double
+ my $ieee_low_bits; # the lower 16 bits of $ieee_double
+ my $higher_32_bits;
+ my $lower_32_bits;
+
+ $ieee_double = get_random_IEEE_double_value();
+
+ # loading a 64 bit double value is going to take some work
+
+ # load the higher 32 bits
+ $higher_32_bits = $ieee_double >> 32; # push the lower 32 bits out
+ $ieee_high_bits = $higher_32_bits >> 16;
+ $ieee_low_bits = $higher_32_bits & 0xffff;
+ write_lis(10, $ieee_high_bits); # lis r10, $ieee_high_bits
+ write_ori(10, 10, $ieee_low_bits); # ori r10, r10,
$ieee_low_bits
+ write_stw(10, $number); # stw r10, $number(r1)
+
+ # load the lower 32 bits
+ $lower_32_bits = $ieee_double & 0xffffffff;
+ $ieee_high_bits = $lower_32_bits >> 16;
+ $ieee_low_bits = $lower_32_bits & 0xffff;
+ write_lis(10, $ieee_high_bits); # lis r10, $ieee_high_bits
+ write_ori(10, 10, $ieee_low_bits); # ori r10, r10,
$ieee_low_bits
+ write_stw(10, $number + 4); # stw r10, $number+4 (r1)
+
+ write_mr($rA, 1); # mr $rA, r1
+ return $rA;
+}
+
+
+# writes ppc assembly code to load a IEEE 754 double value into memory
+# input one: general purpose register number
+# input two: general purpose register number
+# output: IEEE 754 double value
+sub load_double_float_indexed($$)
+{
+ my ($rA, $rB) = @_;
+
+ my $ieee_double; # ieee 754 double float value
+ my $ieee_high_bits; # the upper 16 bits of $ieee_double
+ my $ieee_low_bits; # the lower 16 bits of $ieee_double
+ my $higher_32_bits;
+ my $lower_32_bits;
+
+ $ieee_double = get_random_IEEE_double_value();
+
+ # loading a 64 bit double value is going to take some work
+
+ # load the higher 32 bits
+ $higher_32_bits = $ieee_double >> 32; # push the lower 32 bits out
+ $ieee_high_bits = $higher_32_bits >> 16;
+ $ieee_low_bits = $higher_32_bits & 0xffff;
+ write_lis(10, $ieee_high_bits); # lis r10, $ieee_high_bits
+ write_ori(10, 10, $ieee_low_bits); # ori r10, r10,
$ieee_low_bits
+ write_stw(10, $available_stack_slot); # stw r10,
$available_stack_slot(r1)
+
+ # load the lower 32 bits
+ $lower_32_bits = $ieee_double & 0xffffffff;
+ $ieee_high_bits = $lower_32_bits >> 16;
+ $ieee_low_bits = $lower_32_bits & 0xffff;
+ write_lis(10, $ieee_high_bits); # lis r10,
$ieee_high_bits
+ write_ori(10, 10, $ieee_low_bits); # ori r10, r10,
$ieee_low_bits
+ write_stw(10, $available_stack_slot + 4); # stw r10,
($available_stack_slot + 4)(r1)
+
+ # setup the registers' value
+ write_li($rB, $available_stack_slot); # li $rB,
$available_stack_slot
+ write_mr($rA, 1); # mr $rA, r1
+ return $rA;
+}
+
+# Setup a testing environment for an instruction that
+# requires a double precision floating point value in a float register
+# input: floating point register number
+sub load_double_float_to_reg($)
+{
+ my ($fD) = @_;
+ my $ieee_double; # ieee 754 double float value
+ my $ieee_high_bits; # the upper 16 bits of $ieee_double
+ my $ieee_low_bits; # the lower 16 bits of $ieee_double
+ my $higher_32_bits;
+ my $lower_32_bits;
+
+ $ieee_double = get_random_IEEE_double_value();
+
+ # loading a 64 bit double value is going to take some work
+
+ # load the higher 32 bits
+ $higher_32_bits = $ieee_double >> 32; # push the lower 32 bits
out
+ $ieee_high_bits = $higher_32_bits >> 16;
+ $ieee_low_bits = $higher_32_bits & 0xffff;
+ write_lis(10, $ieee_high_bits); # lis r10, $ieee_high_bits
+ write_ori(10, 10, $ieee_low_bits); # ori r10, r10,
$ieee_low_bits
+ write_stw(10, $available_stack_slot); # stw r10,
$available_stack_slot(r1)
+
+ # load the lower 32 bits
+ $lower_32_bits = $ieee_double & 0xffffffff;
+ $ieee_high_bits = $lower_32_bits >> 16;
+ $ieee_low_bits = $lower_32_bits & 0xffff;
+ write_lis(10, $ieee_high_bits); # lis r10,
$ieee_high_bits
+ write_ori(10, 10, $ieee_low_bits); # ori r10, r10,
$ieee_low_bits
+ write_stw(10, $available_stack_slot + 4); # stw r10,
($available_stack_slot + 4)(r1)
+
+ write_lfd($fD, $available_stack_slot); # lfd $fD,
$available_stack_slot(r1)
+ return -1;
+}
+
+# Setup a testing environment for an instruction that requires
+# a single precision floating point value in a float register
+# input: floating point register number
+sub load_single_float_to_reg($)
+{
+ my ($fD) = @_;
+
+ # load a random single precision floating point value into memory
+ my $float_value = rand();
+ my $ieee_value = convert_to_IEEE($float_value);
+ my $ieee_high_bits; # the upper 16 bits of $ieee_value
+ my $ieee_low_bits; # the lower 16 bits of $ieee_value
+
+ $ieee_high_bits = $ieee_value >> 16;
+ $ieee_low_bits = $ieee_value & 0xffff;
+ write_lis(10, $ieee_high_bits); # lis r10, $ieee_high_bits
+ write_ori(10, 10, $ieee_low_bits); # ori r10, r10,
$ieee_low_bits
+ write_stw(10, $available_stack_slot); # stw r10,
$available_stack_slot(r1)
+ write_lfs($fD, $available_stack_slot); # lfs $fD,
$available_stack_slot(r1)
+
+ return -1; # this just says not not clean up any register
+}
+
+# Compiles the instructions
+# input: hash
+sub gen_one_insn($)
+{
+ # Given an instruction-details array, generate an instruction
+ my $constraintfailures = 0;
+
+ INSN: while(1) {
+ my ($rec) = @_;
+ my $insn = int(rand(0xffffffff));
+ my $insnname = $rec->{name};
+ my $insnwidth = $rec->{width};
+ my $fixedbits = $rec->{fixedbits};
+ my $fixedbitmask = $rec->{fixedbitmask};
+ my $constraint = $rec->{blocks}{"constraints"};
+ my $memblock = $rec->{blocks}{"memory"};
+
+ $insn &= ~$fixedbitmask;
+ $insn |= $fixedbits;
+
+ if (defined $constraint) {
+ # user-specified constraint: evaluate in an environment
+ # with variables set corresponding to the variable fields.
+ my $v = eval_with_fields($insnname, $insn, $rec,
"constraints", $constraint);
+ if (!$v) {
+ $constraintfailures++;
+ if ($constraintfailures > 10000) {
+ print "10000 consecutive constraint failures for
$insnname constraints string:\n$constraint\n";
+ exit (1);
+ }
+ next INSN;
+ }
+ }
+
+ # OK, we got a good one
+ $constraintfailures = 0;
+
+ my $basereg; # The GPR that is used to calculate the load
address
+
+ if (defined $memblock) {
+ # This is a load or store. We simply evaluate the block,
+ # which is expected to be a call to a function which emits
+ # the code to set up the base register and returns the
+ # number of the base register.
+
+ $basereg = eval_with_fields($insnname, $insn, $rec,
"memory", $memblock);
+ }
+
+ debug_print("0x%x ; %s encoding\n", $insn, $insnname);
+ insn32($insn);
+
+ if (defined $memblock && $basereg >= 0) {
+ # cleanup any updated register
+ write_li($basereg, 0);
+ }
+
+ return;
+ }
+}
+
+# writes the instruction that signals risu
+# input: the signal
+sub write_risuop($)
+{
+ # instr with bits (28:27) == 0 0 are UNALLOCATED
+ my ($op) = @_;
+ debug_print("0x%x ; risu request\n", 0x00005af0 | $op);
+ insn32(0x00005af0 | $op);
+}
+
+# write the addi instruction
+# first input: destination register
+# second input: source register
+# third input: number
+sub write_addi($$$)
+{
+ my ($rD, $rA, $number) = @_;
+
+ debug_print("addi r%d, r%d, %d\n", $rD, $rA, $number);
+ # addi rD, rA, number
+ insn32((0xe << 26) | ($rD << 21) | ($rA << 16) | ($number &
0xffff));
+}
+
+# writes the mr instruction
+# first input: destination register
+# second input: source register
+sub write_mr($$)
+{
+ my ($rD, $rS) = @_;
+ my $mr_encoding = 31; # it is really a mnemonic for 'or'
+ my $Rc = 0;
+
+ debug_print("mr r%d, r%d\n", $rD, $rS);
+ insn32($mr_encoding << 26 | $rS << 21 | $rD << 16 | $rS << 11 |
444 << 1 | $Rc);
+}
+
+# writes a stb instruction
+# first input: register number
+# second input: offset from stack pointer
+sub write_stb($$)
+{
+ my ($rS, $offset) = @_;
+ my $stb_encoding = 38;
+ my $stack_pointer = 1; # r1 is the stack pointer
+ debug_print("stb r$rS, $offset(r1)\n");
+ insn32($stb_encoding << 26 | $rS << 21 | $stack_pointer << 16 |
$offset);
+}
+
+# writes a stw instruction
+# first input: register number
+# second input: offset from stack pointer
+sub write_stw($$)
+{
+ my ($rS, $offset) = @_;
+ my $stw_encoding = 36;
+ my $stack_pointer = 1; # r1 is the stack pointer
+ debug_print("stw r$rS, $offset(r1)\n");
+ insn32($stw_encoding << 26 | $rS << 21 | $stack_pointer << 16 |
$offset);
+}
+
+# writes a lfs instruction
+# first input: floating point register number
+# second input: offset from stack pointer
+sub write_lfs($$)
+{
+ my ($fD, $offset) = @_;
+ my $lfs_encoding = 48;
+ my $stack_pointer = 1; # r1 is the stack pointer
+ debug_print("lfs f$fD, $offset(r1)\n");
+ insn32($lfs_encoding << 26 | $fD << 21 | $stack_pointer << 16 |
$offset);
+}
+
+# writes a lfd instruction
+# first input: floating point register number
+# second input: offset value
+sub write_lfd($$)
+{
+ my ($fD, $offset) = @_;
+ my $lfd_encoding = 50;
+ my $stack_pointer = 1; # r1 is the stack pointer
+ debug_print("lfd f$fD, $offset(r$stack_pointer)\n");
+ insn32($lfd_encoding << 26 | $fD << 21 | $stack_pointer << 16 |
$offset);
+}
+
+# write the "li rx, value" instruction
+# first input: the register number
+# second input: the value
+sub write_li($$)
+{
+ my ($rD, $value) = @_;
+ debug_print("li r%d, 0x%x\n", $rD, $value);
+ insn32(0xe << 26 | $rD << 21 | $value);
+}
+
+# writes the lis instruction
+# first input: register number
+# second input: value
+sub write_lis($$)
+{
+ my ($register, $value) = @_;
+ my $lis_encoding = 15;
+ debug_print("lis r%d, 0x%x\n", $register, $value);
+ insn32($lis_encoding << 26 | $register << 21 | 0 << 16 | $value);
+}
+
+# writes the ori instruction
+# first input: destination register
+# second input: source register
+# third input: number
+sub write_ori($$$)
+{
+ my ($dest_reg, $source_reg, $number) = @_;
+ my $ori_encoding = 24;
+ debug_print("ori r%d, r%d, 0x%x\n", $dest_reg, $source_reg,
$number);
+ insn32($ori_encoding << 26 | $dest_reg << 21 | $source_reg << 16
| $number);
+}
+
+# writes the mtfsb0 instruction
+# input: fpscr field number
+sub write_mtfsb0($)
+{
+ my $mtfsb0_encoding = 63;
+ my $crbD = $_[0];
+ my $Rc = 0;
+ debug_print("mtfsb0 %d\n", $crbD);
+ insn32($mtfsb0_encoding << 26 | $crbD << 21 | 70 << 1 | $Rc);
+}
+
+# writes the mtfsb1 instruction
+# input: fpscr field number
+sub write_mtfsb1($)
+{
+ my $mtfsb1_encoding = 63;
+ my $crbD = $_[0];
+ my $Rc = 0;
+ debug_print("mtfsb1 %d\n", $crbD);
+ insn32($mtfsb1_encoding << 26 | $crbD << 21 | 38 << 1 | $Rc);
+}
+
+# writes the mtxer instruction
+# first input: source register
+sub write_mtxer($)
+{
+ my ($rS) = @_;
+ my $mtspr_encoding = 31; # mtxer is really mtspr
+ my $spr = 16;
+ my $raw_encoding;
+
+ debug_print("mtxer r%d\n", $rS);
+ $raw_encoding = $mtspr_encoding << 26 | $rS << 21 | $spr << 12 |
467 << 1 | 0;
+ insn32($raw_encoding);
+}
+
+# writes the mtcrf instruction
+# first input: condition register mask
+# second input: source register
+sub write_mtcrf($$)
+{
+ my ($CRM, $rS) = @_;
+ my $mtcrf_encoding = 31;
+ debug_print("mtcrf %d, r%d\n", $CRM, $rS);
+ insn32($mtcrf_encoding << 26 | $rS << 21 | $CRM << 12 | 144 << 1);
+}
+
+# setup the testing environment for the lmw instruction
+# first input: general purpose register number
+# second input: general purpose regiser number
+# third input: immediate value
+# ouptut: general purpose register number
+sub setup_lmw_test($$$)
+{
+ my ($rD, $rA, $imm) = @_;
+ for(my $i = 0; $i < (32 - $rD); $i++) {
+ write_li(10, $i); # li r10, $i
+ write_stw(10, $imm + ($i * 4)); # stw r10, ($imm + $i *
4)(r1)
+ }
+ write_mr($rA, 1); # mr $rA, r1
+ debug_print("lmw r$rD, $imm(r$rA)\n");
+ return $rA;
+}
+
+# setup the testing environment for the lswi instruction
+# first input: general purpose register number
+# second input: general purpose register number
+# third input: number of bytes to load
+# output: general purpose register number
+sub setup_lswi_test($$$)
+{
+ my ($rD, $rA, $NB) = @_;
+ my $imm;
+
+ write_lis(10, 0xabcd); # lis r10, 0x6861
+ write_ori(10, 10, 0xef12); # ori r10, r10, 0x636B
+
+ # fill the memory with $NB bytes of data
+ for(my $i = 0; $i < $NB; $i++) {
+ $imm = $available_stack_slot + $i * 4;
+ write_stw(10, $imm); # stw r10, $imm(r1)
+ }
+ write_mr($rA, 1); # mr $rA, r1
+ write_addi($rA, $rA, $available_stack_slot); # addi $rA, $rA,
$available_stack_slot
+ debug_print("lswi r$rD, r$rA, $NB\n");
+ return $rA;
+}
+
+# setup the testing environment for the lswx instruction
+# first input: general purpose register number
+# second input: general purpose register number
+# third input: general purpose register number
+# output: general purpose register number
+sub setup_lswx_test($$$)
+{
+ my ($rD, $rA, $rB) = @_;
+ my $bytes_per_register = 4; # four bytes can fit in one
general purpose register
+ my $num_gpr = 32; # the number of general purpose registers
+
+ # This prevents LSWX from wrapping around and loading r0
+ my $num_bytes = int rand(64);
+ if (($num_bytes/$bytes_per_register) > ($num_gpr - $rD)) {
+ $num_bytes = ($num_gpr - $rD) * $bytes_per_register;
+ }
+
+ # Prevent registers rA and rB from being in the loading path
+
+ my $regA = 0;
+ my $regB = 0;
+ my $closest_register;
+ my $overlap;
+
+ # determine distance from register rD
+ if ($rA - $rD > 0) {
+ $regA = $rA;
+ }
+
+ if ($rB - $rD > 0) {
+ $regB = $rB;
+ }
+
+ # both rA and rB are in the load path
+ if ($regA > 0 && $regB > 0) {
+ # find the register closest to rD
+ $closest_register = ($regA < $regB) ? $regA : $regB;
+ }
+
+ # only rA is in the load path
+ elsif ($regA != 0 && $regB == 0) {
+ $closest_register = $regA;
+ }
+
+ # only rB is in the load path
+ elsif ($regA == 0 && $regB != 0) {
+ $closest_register = $regB;
+ }
+
+ # no register is in the load path
+ else {
+ $closest_register = -1;
+ }
+
+ # calculate new safe value for num_bytes
+ if ($closest_register != -1 && $num_bytes >= ($closest_register
- $rD) * $bytes_per_register) {
+ $num_bytes = ($closest_register - $rD) * $bytes_per_register;
+ }
+
+ write_li(10, $num_bytes); # li r10,
$num_bytes
+ write_mtxer(10); # mtxer r10
+
+ # Fill memory with values
+ for(my $i = 0; $i < $num_bytes; $i++) {
+ write_li(10, $i + 1); # li r10,
($i+1)
+ write_stb(10, $available_stack_slot + $i); # stb r10,
($available_stack_slot + $i)(r1)
+ }
+
+ write_mr($rA, 1); # mr $rA, r1
+ write_li($rB, $available_stack_slot); # li $rB,
$available_stack_slot
+
+ debug_print("lswx r$rD, r$rA, r$rB ; xer:$num_bytes\n");
+
+ return $rA;
+}
+
+# writes the code that sets the general purpose registers
+sub write_init_gpr_code()
+{
+ # Set the general purpose registers to a value.
+ # Register r1 is the stack pointer.
+ # It is left alone.
+ for (my $i = 0; $i < 32; $i++) {
+ if ($i == 1) {
+ next;
+ }
+ write_li($i, $i + 1);
+ }
+}
+
+# set the initial value to all floating point registers
+sub write_init_float_registers_code()
+{
+ my $value = 1.1;
+ my $ieee_value;
+ my $ieee_high_bits; # the upper 16 bits of $ieee_value
+ my $ieee_low_bits; # the lower 16 bits of $ieee_value
+
+ for(my $i = 0; $i < 32; $i++) {
+ $ieee_value = convert_to_IEEE($value + $i);
+ $ieee_high_bits = $ieee_value >> 16;
+ $ieee_low_bits = $ieee_value & 0xffff;
+ write_lis(10, $ieee_high_bits); # lis r10,
$ieee_high_bits
+ write_ori(10, 10, $ieee_low_bits); # ori r10, r10,
$ieee_low_bits
+ write_stw(10, $available_stack_slot); # stw r10,
$available_stack_slot(r1)
+ write_lfs($i, $available_stack_slot); # lfs fD,
$available_stack_slot(r1)
+ }
+}
+
+# set the fpscr to the requested value
+# input: value
+sub write_init_fpscr_code($)
+{
+ my ($value) = @_;
+ my $num_fpscr_fields = 32;
+
+ for (my $i = 0; $i < $num_fpscr_fields; $i++) {
+ if (($value >> $i) & 0x1) {
+ write_mtfsb1($i);
+ }
+ else {
+ write_mtfsb0($i);
+ }
+ }
+}
+
+# sets the xer register to zero
+sub write_init_xer_code()
+{
+ my $rS = 10;
+ my $value = 0;
+ write_li($rS, $value);
+ write_mtxer($rS);
+}
+
+# sets the lr to zero
+sub write_init_lr_code()
+{
+ my $rS = 10;
+ my $value = 0;
+ write_li($rS, $value);
+ debug_print("mtlr r%d\n", $rS);
+ insn32(0x7d4803a6);
+}
+
+# set the ctr to zero
+sub write_init_ctr_code()
+{
+ my $rS = 10;
+ my $value = 0;
+ write_li($rS, $value);
+ debug_print("mtctr r%d\n", $rS);
+ insn32(0x7d4903a6);
+}
+
+
+# set the condition register to zero
+sub write_init_cr_code()
+{
+ my $r10 = 10;
+ my $value = 0;
+ my $CRM = 0xff;
+ write_li($r10, $value);
+ write_mtcrf($CRM, $r10);
+}
+
+# This is called by the risugen program.
+# Execution starts here.
+# input: hash
+sub write_test_code($)
+{
+ my ($params) = @_;
+ my $numinsns = $params->{ 'numinsns' };
+ my $fp_enabled = $params->{ 'fp_enabled' };
+ my $outfile = $params->{ 'outfile' };
+ my $fpscr = $params->{ 'fpscr' };
+ my @pattern_re = @{ $params->{ 'pattern_re' } };
+ my @not_pattern_re = @{ $params->{ 'not_pattern_re' } };
+ my %insn_details = %{ $params->{ 'details' } };
+
+ set_endian(1); # Set to big endian
+ open_bin($outfile);
Add the risugen_ppc.pm file. It is used to generate the instructions that risu runs. Signed-off-by: John Arbuckle <programmingkidx@gmail.com> --- risugen_ppc.pm | 744 +++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++ 1 file changed, 744 insertions(+) create mode 100644 risugen_ppc.pm + srand(); + + # Get a list of the insn keys which are permitted by the re patterns + my @keys = sort keys %insn_details; + if (@pattern_re) { + my $re = '\b((' . join(')|(',@pattern_re) . '))\b'; + @keys = grep /$re/, @keys; + } + # exclude any specifics + if (@not_pattern_re) { + my $re = '\b((' . join(')|(',@not_pattern_re) . '))\b'; + @keys = grep !/$re/, @keys; + } + if (!@keys) { + print STDERR "No instruction patterns available! (bad config file or --pattern argument?)\n"; + exit(1); + } + print "Generating code using patterns: @keys...\n"; + progress_start(78, $numinsns); + + # initialize all the UISA registers + write_init_gpr_code(); + + if ($fp_enabled) { + write_init_float_registers_code(); + write_init_fpscr_code($fpscr); + } + + write_init_xer_code(); + write_init_lr_code(); + write_init_ctr_code(); + write_init_cr_code(); + write_risuop($OP_COMPARE); + + for my $i (1..$numinsns) { + my $insn_enc = $keys[int rand (@keys)]; + #dump_insn_details($insn_enc, $insn_details{$insn_enc}); + gen_one_insn($insn_details{$insn_enc}); + write_risuop($OP_COMPARE); + if ($debug != 1) { + progress_update($i); + } + } + write_risuop($OP_TESTEND); + progress_end(); + close_bin(); +} + +1;