// File: jstaursky[P]hutch/src/Sleigh/pcodecompile.cc
// Function: PcodeCompile::createBitRange(SpecificSymbol*, unsigned int, unsigned int)
ExprTree *PcodeCompile::createBitRange(SpecificSymbol *sym,uint4 bitoffset,uint4 numbits)

{ // Create an expression computing the indicated bitrange of sym
  // The result is truncated to the smallest byte size that can
  // contain the indicated number of bits. The result has the
  // desired bits shifted all the way to the right
  string errmsg;
  if (numbits == 0)
    errmsg = "Size of bitrange is zero";
  VarnodeTpl *vn = sym->getVarnode();
  uint4 finalsize = (numbits+7)/8; // Round up to neareast byte size
  uint4 truncshift = 0;
  bool maskneeded = ((numbits%8)!=0);
  bool truncneeded = true;

  // Special case where we can set the size, without invoking
  // a truncation operator
  if ((errmsg.size()==0)&&(bitoffset==0)&&(!maskneeded)) {
    if ((vn->getSpace().getType()==ConstTpl::handle)&&vn->isZeroSize()) {
      vn->setSize(ConstTpl(ConstTpl::real,finalsize));
      ExprTree *res = new ExprTree(vn);
      //      VarnodeTpl *cruft = buildTemporary();
      //      delete cruft;
      return res;
    }
  }

  if (errmsg.size()==0) {
    VarnodeTpl *truncvn = buildTruncatedVarnode(vn,bitoffset,numbits);
    if (truncvn != (VarnodeTpl *)0) { // If we are able to construct a simple truncated varnode
      ExprTree *res = new ExprTree(truncvn); // Return just the varnode as an expression
      delete vn;
      return res;
    }
  }

  if (vn->getSize().getType()==ConstTpl::real) {
    // If we know the size of the input varnode, we can
    // do some immediate checks, and possibly simplify things
    uint4 insize = vn->getSize().getReal();
    if (insize > 0) {
      truncneeded = (finalsize < insize);
      insize *= 8;		// Convert to number of bits
      if ((bitoffset >= insize)||(bitoffset+numbits > insize))
	errmsg = "Bitrange is bad";
      if (maskneeded && ((bitoffset+numbits)==insize))
	maskneeded = false;
    }
  }

  uintb mask = (uintb)2;
  mask = ((mask<<(numbits-1))-1);
  
  if (truncneeded && ((bitoffset % 8)==0)) {
    truncshift = bitoffset/8;
    bitoffset = 0;
  }

  if ((bitoffset==0)&&(!truncneeded)&&(!maskneeded))
    errmsg = "Superfluous bitrange";

  if (maskneeded && (finalsize > 8))
    errmsg = "Illegal masked bitrange producing varnode larger than 64 bits: " + sym->getName();

  ExprTree *res = new ExprTree(vn);

  if (errmsg.size()>0) {	// Check for error condition
    reportError(errmsg);
    return res;
  }

  if (bitoffset !=0)
    appendOp(CPUI_INT_RIGHT,res,bitoffset,4);
  if (truncneeded)
    appendOp(CPUI_SUBPIECE,res,truncshift,4);
  if (maskneeded)
    appendOp(CPUI_INT_AND,res,mask,finalsize);
  force_size(res->outvn,ConstTpl(ConstTpl::real,finalsize),*res->ops);
  return res;
}

// Assembly:
subq $0x188, %rsp            # imm = 0x188
movq %rdi, 0x178(%rsp)
movq %rsi, 0x170(%rsp)
movl %edx, 0x16c(%rsp)
movl %ecx, 0x168(%rsp)
movq 0x178(%rsp), %rax
movq %rax, 0x80(%rsp)
leaq 0x148(%rsp), %rdi
callq 0xdc610
cmpl $0x0, 0x168(%rsp)
jne 0x11080d
leaq 0x777d1(%rip), %rsi     # 0x187fb4
leaq 0x148(%rsp), %rdi
callq 0xdc010
jmp 0x1107f2
jmp 0x11080d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
jmp 0x110e7e
movq 0x170(%rsp), %rdi
movq (%rdi), %rax
movq 0x60(%rax), %rax
callq *%rax
movq %rax, 0x78(%rsp)
jmp 0x110825
movq 0x78(%rsp), %rax
movq %rax, 0x130(%rsp)
movl 0x168(%rsp), %eax
addl $0x7, %eax
shrl $0x3, %eax
movl %eax, 0x12c(%rsp)
movl $0x0, 0x128(%rsp)
movl 0x168(%rsp), %eax
andl $0x7, %eax
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movb %al, 0x127(%rsp)
movb $0x1, 0x126(%rsp)
leaq 0x148(%rsp), %rdi
callq 0xd5290
cmpq $0x0, %rax
jne 0x1109ad
cmpl $0x0, 0x16c(%rsp)
jne 0x1109ad
testb $0x1, 0x127(%rsp)
jne 0x1109ad
movq 0x130(%rsp), %rdi
callq 0xe3000
movq %rax, 0x70(%rsp)
jmp 0x1108b9
movq 0x70(%rsp), %rdi
callq 0xde5d0
movl %eax, 0x6c(%rsp)
jmp 0x1108c9
movl 0x6c(%rsp), %eax
cmpl $0x1, %eax
jne 0x1109ab
movq 0x130(%rsp), %rdi
callq 0xdd230
movb %al, 0x6b(%rsp)
jmp 0x1108e9
movb 0x6b(%rsp), %al
testb $0x1, %al
jne 0x1108f6
jmp 0x1109ab
movq 0x130(%rsp), %rax
movq %rax, 0x60(%rsp)
movl 0x12c(%rsp), %eax
movl %eax, %edx
leaq 0x100(%rsp), %rdi
xorl %esi, %esi
callq 0xd9880
jmp 0x11091d
movq 0x60(%rsp), %rdi
leaq 0x100(%rsp), %rsi
callq 0xe29d0
jmp 0x110931
movl $0x10, %edi
callq 0xd8380
movq %rax, 0x58(%rsp)
jmp 0x110942
movq 0x58(%rsp), %rdi
movq 0x130(%rsp), %rsi
callq 0xd1cc0
jmp 0x110956
movq 0x58(%rsp), %rax
movq %rax, 0xf8(%rsp)
movq 0xf8(%rsp), %rax
movq %rax, 0x180(%rsp)
movl $0x1, 0xf4(%rsp)
jmp 0x110e61
movq 0x58(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
movl $0x10, %esi
callq 0xd8620
jmp 0x110e7e
jmp 0x1109ad
leaq 0x148(%rsp), %rdi
callq 0xd5290
cmpq $0x0, %rax
jne 0x110aa8
movq 0x80(%rsp), %rdi
movq 0x130(%rsp), %rsi
movl 0x16c(%rsp), %edx
movl 0x168(%rsp), %ecx
callq 0xd8550
movq %rax, 0x50(%rsp)
jmp 0x1109ee
movq 0x50(%rsp), %rax
movq %rax, 0xe8(%rsp)
cmpq $0x0, 0xe8(%rsp)
je 0x110aa6
movl $0x10, %edi
callq 0xd8380
movq %rax, 0x48(%rsp)
jmp 0x110a1b
movq 0x48(%rsp), %rdi
movq 0xe8(%rsp), %rsi
callq 0xd1cc0
jmp 0x110a2f
movq 0x48(%rsp), %rax
movq %rax, 0xe0(%rsp)
movq 0x130(%rsp), %rax
movq %rax, 0x40(%rsp)
cmpq $0x0, %rax
je 0x110a5e
movq 0x40(%rsp), %rdi
movl $0x68, %esi
callq 0xd8620
movq 0xe0(%rsp), %rax
movq %rax, 0x180(%rsp)
movl $0x1, 0xf4(%rsp)
jmp 0x110e61
movq 0x48(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
movl $0x10, %esi
callq 0xd8620
jmp 0x110e7e
jmp 0x110aa8
movq 0x130(%rsp), %rdi
callq 0xd4930
movq %rax, 0x38(%rsp)
jmp 0x110abc
movq 0x38(%rsp), %rdi
callq 0xde5d0
movl %eax, 0x34(%rsp)
jmp 0x110acc
movl 0x34(%rsp), %eax
cmpl $0x0, %eax
jne 0x110baf
movq 0x130(%rsp), %rdi
callq 0xd4930
movq %rax, 0x28(%rsp)
jmp 0x110aed
movq 0x28(%rsp), %rdi
callq 0xdd890
movq %rax, 0x20(%rsp)
jmp 0x110afe
movq 0x20(%rsp), %rax
movl %eax, 0xdc(%rsp)
cmpl $0x0, 0xdc(%rsp)
jbe 0x110bad
movl 0x12c(%rsp), %eax
cmpl 0xdc(%rsp), %eax
setb %al
andb $0x1, %al
movb %al, 0x126(%rsp)
movl 0xdc(%rsp), %eax
shll $0x3, %eax
movl %eax, 0xdc(%rsp)
movl 0x16c(%rsp), %eax
cmpl 0xdc(%rsp), %eax
jae 0x110b6a
movl 0x16c(%rsp), %eax
addl 0x168(%rsp), %eax
cmpl 0xdc(%rsp), %eax
jbe 0x110b82
leaq 0x774c7(%rip), %rsi     # 0x188038
leaq 0x148(%rsp), %rdi
callq 0xdc010
jmp 0x110b80
jmp 0x110b82
testb $0x1, 0x127(%rsp)
je 0x110bab
movl 0x16c(%rsp), %eax
addl 0x168(%rsp), %eax
cmpl 0xdc(%rsp), %eax
jne 0x110bab
movb $0x0, 0x127(%rsp)
jmp 0x110bad
jmp 0x110baf
movq $0x2, 0xd0(%rsp)
movq 0xd0(%rsp), %rax
movl 0x168(%rsp), %ecx
subl $0x1, %ecx
movl %ecx, %ecx
shlq %cl, %rax
subq $0x1, %rax
movq %rax, 0xd0(%rsp)
testb $0x1, 0x126(%rsp)
je 0x110c13
movl 0x16c(%rsp), %eax
andl $0x7, %eax
cmpl $0x0, %eax
jne 0x110c13
movl 0x16c(%rsp), %eax
shrl $0x3, %eax
movl %eax, 0x128(%rsp)
movl $0x0, 0x16c(%rsp)
cmpl $0x0, 0x16c(%rsp)
jne 0x110c49
testb $0x1, 0x126(%rsp)
jne 0x110c49
testb $0x1, 0x127(%rsp)
jne 0x110c49
leaq 0x77410(%rip), %rsi     # 0x188048
leaq 0x148(%rsp), %rdi
callq 0xdc010
jmp 0x110c47
jmp 0x110c49
testb $0x1, 0x127(%rsp)
je 0x110cae
cmpl $0x8, 0x12c(%rsp)
jbe 0x110cae
movq 0x170(%rsp), %rdi
callq 0xd1f90
movq %rax, 0x18(%rsp)
jmp 0x110c71
movq 0x18(%rsp), %rdx
leaq 0x773e0(%rip), %rsi     # 0x18805d
leaq 0xb0(%rsp), %rdi
callq 0xd7370
jmp 0x110c8c
leaq 0x148(%rsp), %rdi
leaq 0xb0(%rsp), %rsi
callq 0xda960
leaq 0xb0(%rsp), %rdi
callq 0xd4550
movl $0x10, %edi
callq 0xd8380
movq %rax, 0x10(%rsp)
jmp 0x110cbf
movq 0x10(%rsp), %rdi
movq 0x130(%rsp), %rsi
callq 0xd1cc0
jmp 0x110cd3
movq 0x10(%rsp), %rax
movq %rax, 0xa8(%rsp)
leaq 0x148(%rsp), %rdi
callq 0xd5290
cmpq $0x0, %rax
jbe 0x110d56
movq 0x80(%rsp), %rdi
movq (%rdi), %rax
movq 0x20(%rax), %rax
leaq 0x148(%rsp), %rsi
callq *%rax
jmp 0x110d0e
movq 0xa8(%rsp), %rax
movq %rax, 0x180(%rsp)
movl $0x1, 0xf4(%rsp)
jmp 0x110e61
movq 0x10(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
movl $0x10, %esi
callq 0xd8620
jmp 0x110e7e
cmpl $0x0, 0x16c(%rsp)
je 0x110d8d
movq 0x80(%rsp), %rdi
movq 0xa8(%rsp), %rdx
movl 0x16c(%rsp), %eax
movl %eax, %ecx
movl $0x1e, %esi
movl $0x4, %r8d
callq 0xd6ab0
jmp 0x110d8b
jmp 0x110d8d
testb $0x1, 0x126(%rsp)
je 0x110dc4
movq 0x80(%rsp), %rdi
movq 0xa8(%rsp), %rdx
movl 0x128(%rsp), %eax
movl %eax, %ecx
movl $0x3f, %esi
movl $0x4, %r8d
callq 0xd6ab0
jmp 0x110dc2
jmp 0x110dc4
testb $0x1, 0x127(%rsp)
je 0x110dfc
movq 0x80(%rsp), %rdi
movq 0xa8(%rsp), %rdx
movq 0xd0(%rsp), %rcx
movl 0x12c(%rsp), %r8d
movl $0x1b, %esi
callq 0xd6ab0
jmp 0x110dfa
jmp 0x110dfc
movq 0xa8(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x8(%rsp)
movl 0x12c(%rsp), %eax
movl %eax, %edx
leaq 0x88(%rsp), %rdi
xorl %esi, %esi
callq 0xd9880
jmp 0x110e27
movq 0x8(%rsp), %rdi
movq 0xa8(%rsp), %rax
movq (%rax), %rdx
leaq 0x88(%rsp), %rsi
callq 0xcf5c0
jmp 0x110e46
movq 0xa8(%rsp), %rax
movq %rax, 0x180(%rsp)
movl $0x1, 0xf4(%rsp)
leaq 0x148(%rsp), %rdi
callq 0xd4550
movq 0x180(%rsp), %rax
addq $0x188, %rsp            # imm = 0x188
retq
leaq 0x148(%rsp), %rdi
callq 0xd4550
movq 0x140(%rsp), %rdi
callq 0xe0be0
nopl (%rax,%rax)