// This is a SyReC-file describing the arithmetic-logic unit of a RISC CPU as specified in [WSG+:2011] with a bit-width of 32.
// This file has been taken from RevLib (www.revlib.org). 

module alu( in aluEnable(1), in oprt(4), in oprd1(32), in oprd2(32),
            out data(32),
            inout cCarry(1), inout cZero(1) )
 wire op1(33), op2(33), data_tmp(33), tmp(1), cZero_copy(1)

  

  op1.0:31 ^= oprd1;
  op2.0:31 ^= oprd2;

  if !aluEnable then
    data_tmp ^= op1
  else
    if ( oprt = 0 ) then
      ~= data_tmp 
    else
      if ( oprt = 1 ) then
        data_tmp ^= ( op1 ^ op2 )
      else
        if ( oprt = 2 ) then
          data_tmp ^= ( op1 | op2 )
        else
          if ( oprt = 3 ) then
            data_tmp ^= ( op1 & op2 )
          else
            if ( oprt = 4 ) then
              data_tmp ^= ( op1 << 1 );
              cCarry <=> op1.31
            else
              if ( oprt = 5 ) then
                data_tmp ^= ( op1 >> 1 );
                cCarry <=> op1.0
              else
                if ( oprt = 6 ) then
                  data_tmp ^= ( op1 - op2 );
                  tmp ^= ( data_tmp.32 ^ cCarry );
                  cCarry ^= tmp
                else
                  if ( oprt = 7 ) then
                    data_tmp ^= ( op1 + op2 );
                    tmp ^= ( data_tmp.32 ^ cCarry );
                    cCarry ^= tmp
                  else
                    if ( oprt = 8 ) then
                      for $i = 0 to 31 do
                        if ( op2 = $i ) then
                          data_tmp.$i ^= op1.$i
                        else
                          skip
                        fi ( op2 = $i )
                      rof
                    else
                      if ( oprt = 9 ) then
                        data_tmp ^= op1;
                        for $i = 0 to 31 do
                          if ( op2 = $i ) then
                            ~= data_tmp.$i
                          else
                            skip
                          fi ( op2 = $i )
                        rof
                      else
                        if ( oprt = 10 ) then
                          data_tmp ^= op1;
                          for $i = 0 to 31 do
                            if ( op2 = $i ) then
                              data_tmp.$i <=> tmp;
                              ~= data_tmp.$i
                            else
                              skip
                            fi ( op2 = $i )
                          rof
                        else
                          if ( oprt = 11 ) then
                            data_tmp ^= op1;
                            for $i = 0 to 31 do
                              if ( op2 = $i ) then
                                data_tmp.$i <=> tmp
                              else
                                skip
                              fi ( op2 = $i )
                            rof
                          else
                            if ( oprt = 12 ) then
                              data_tmp ^= ( op1 << 1 );
                              data_tmp.0 ^= cCarry;
                              cCarry <=> op1.31
                            else
                              if ( oprt = 13 ) then
                                data_tmp ^= ( op1 >> 1 );
                                data_tmp.31 <=> cCarry;
                                cCarry <=> op1.0
                              else
                                if ( oprt = 14 ) then
                                  data_tmp ^= ( op1 - op2 );
                                  if cCarry then
                                    --= data_tmp
                                  else
                                    skip
                                  fi cCarry;
                                  tmp ^= ( data_tmp.32 ^ cCarry );
                                  cCarry ^= tmp
                                else
                                  if ( oprt = 15 ) then
                                    data_tmp ^= ( op1 + op2 );
                                    if cCarry then
                                      ++= data_tmp
                                    else
                                      skip
                                    fi cCarry;
                                    tmp ^= ( data_tmp.32 ^ cCarry );
                                    cCarry ^= tmp
                                  else
                                    skip
                                  fi ( oprt = 15 )
                                fi ( oprt = 14 )
                              fi ( oprt = 13 )
                            fi ( oprt = 12 )
                          fi ( oprt = 11 )
                        fi ( oprt = 10 )
                      fi ( oprt = 9 )
                    fi ( oprt = 8 )
                  fi ( oprt = 7 )
                fi ( oprt = 6 )
              fi ( oprt = 5 )
            fi ( oprt = 4 )
          fi ( oprt = 3 )
        fi ( oprt = 2 )
      fi ( oprt = 1 )
    fi ( oprt = 0 );
    cZero_copy ^= cZero;
    if ( !cZero_copy && ( data_tmp = 0 ) ) then
      ~= cZero
    else
      if ( cZero_copy && ( data_tmp != 0 ) ) then
        ~= cZero
      else
        skip
      fi ( cZero_copy && ( data_tmp != 0 ) )
    fi ( !cZero_copy  && ( data_tmp = 0 ) )
  fi !aluEnable;

  data ^= data_tmp.0:31
