Skip to content

Commit

Permalink
Support for conversion from Instruction API objects to Rose SgAsmInst…
Browse files Browse the repository at this point in the history
…ruction objects for ARMv8

This commit is the first in a branch that will contain all changes for enabling the conversion from ARMv8 Instruction API objects to SgAsmInstruction objects. Since ROSE doesn't support ARMv8, the instruction representation for it has been added by extending SgAsmInstruction. getROSERegister is also modified to map Dyninst registers to ROSE ARMv8 registers, which have again been newly added and are defined in the armv8InstructionEnum file. ROSE instruction factory for ARMv8 does not perform any processing to Instruction API operands when performing the conversion (unlike x86 and Power) -- this is primarily because there is no existing ARMv8 semantics to conform to.

This commit also brings in lots of changes to the ROSE interface for representing an instruction and its parts:
* SgAsm*ValueExpression types are now replaces with SgAsm(Integer/Float)ValueExpression types; SgAsmType* have been replaced by SgAsmType(Integer/Float). The old classes remain to support the existing x86/Power semantics.
* Several changes are made to the classes that were already present. These changes support existing semantics and will also work for ARMv8.
* New classes have been added for representation of expressions.
* Several classes in the Sawyer namespace of ROSE have been added -- these are used in the newly introduced Sg* classes, and will also be used for ARM semantics.
* ROSE's new representation for registers uses RegisterDescriptor and a new class for register expressions (SgAsmDirectRegisterExoression).
* The new types are used based on a check on the architecture.
* Opcodes for ARMv8 have the same name in ROSE as in Dyninst, except that the name is prefixed by the string "rose_".
  • Loading branch information
ssunny7 committed Jun 7, 2016
1 parent 38868b2 commit 26a67de
Show file tree
Hide file tree
Showing 34 changed files with 14,466 additions and 1,579 deletions.
31 changes: 29 additions & 2 deletions common/src/dyn_regs.C
Expand Up @@ -33,6 +33,7 @@

#include "external/rose/rose-compat.h"
#include "external/rose/powerpcInstructionEnum.h"
#include "external/rose/armv8InstructionEnum.h"

#include <iostream>

Expand Down Expand Up @@ -809,9 +810,35 @@ void MachRegister::getROSERegister(int &c, int &n, int &p)
break;
case Arch_aarch64:
{
assert(0);
return;
switch(category) {
case aarch64::GPR: {
c = armv8_regclass_gpr;
if(baseID == aarch64::zr || baseID == aarch64::wzr)
n = armv8_gpr_zr;
else {
int regnum = baseID - aarch64::x0;
n = armv8_gpr_r0 + regnum;
}
}
break;
case aarch64::SPR: {
n = 0;
if(baseID == aarch64::pstate) {
c = armv8_regclass_pstate;
n = armv8_pstatefield_nzcv;
} else if(baseID == aarch64::pc) {
c = armv8_regclass_pc;
} else if(baseID == aarch64::sp || baseID == aarch64::wsp) {
c = armv8_regclass_sp;
}
}
break;
default:assert(!"unknown register type!");
break;
}
return;
}
break;
default:
c = x86_regclass_unknown;
n = 0;
Expand Down
76 changes: 76 additions & 0 deletions dataflowAPI/rose/RegisterDescriptor.h
@@ -0,0 +1,76 @@
//
// Created by ssunny on 5/26/16.
//

#ifndef DYNINST_REGISTERDESCRIPTOR_H
#define DYNINST_REGISTERDESCRIPTOR_H

#include <iostream>

/** Describes (part of) a physical CPU register.
*
* Some architectures have multiple names for physical registers. For example, a amd64 has a 64-bit integer register, parts
* of which are referred to as "rax", "eax", "ax", "al", and "ah". The purpose of a RegisterDescriptor is to describe what
* physical register (major and minor) is being referenced, and the part (offset and nbits) that's being referenced.
*
* The reason for having a major and minor number to specify a register is to allow for different types of registers. For
* instance, an i686 has a set of 64-bit integer registers and a set of 80-bit floating point registers (among others).
* Having major and minor numbers allows the physical register set (such as defined by an instruction semantics policy) to
* be implemented as an array of 64-bit integers and an array of 80-bit floating points (among others). The array is selected
* by the major number while the element of the array is selected by the minor number.
*
* The RegisterDescriptor type is part of a SgAsmRegisterReferenceExpression and also appears in the register dictionaries
* (RegisterDictionary) used in various places including the disassembler. */
struct RegisterDescriptor {
public:
RegisterDescriptor()
: majr(0), minr(0), offset(0), nbits(0) {}
RegisterDescriptor(unsigned majr, unsigned minr, unsigned offset, unsigned nbits)
: majr(majr), minr(minr), offset(offset), nbits(nbits) {}
unsigned get_major() const {
return majr;
}
bool is_valid() const {
return nbits!=0;
}
RegisterDescriptor &set_major(unsigned majr) {
this->majr = majr;
return *this;
}
unsigned get_minor() const {
return minr;
}
RegisterDescriptor &set_minor(unsigned minr) {
this->minr = minr;
return *this;
}
unsigned get_offset() const {
return offset;
}
RegisterDescriptor &set_offset(unsigned offset) {
this->offset = offset;
return *this;
}
unsigned get_nbits() const {
return nbits;
}
RegisterDescriptor &set_nbits(unsigned nbits) {
this->nbits = nbits;
return *this;
}
bool operator<(const RegisterDescriptor &other) const;
bool operator==(const RegisterDescriptor &other) const;
bool operator!=(const RegisterDescriptor &other) const;
void print(std::ostream &o) const {
o <<"{" <<majr <<"," <<minr <<"," <<offset <<"," <<nbits <<"}";
}
friend std::ostream& operator<<(std::ostream&, const RegisterDescriptor&); /*in Register.C*/
private:
/* Strange names "majr" and "minr" are to avoid a conflict with "major" and "minor" macros in some non-standard headers. */
unsigned majr; /** Major type of register, such as integer, floating point, flag, etc. */
unsigned minr; /** Register number within major division. */
unsigned offset; /** Low-bit offset within the physical register. */
unsigned nbits; /** Number of bits referenced by this descriptor. */
};

#endif //DYNINST_REGISTERDESCRIPTOR_H
51 changes: 51 additions & 0 deletions dataflowAPI/rose/SgAsmArmv8Instruction.h
@@ -0,0 +1,51 @@
#ifndef SG_ASM_ARMV8_INSN_H
#define SG_ASM_ARMV8_INSN_H

#include "external/rose/armv8InstructionEnum.h"
#include "typedefs.h"
#include "SgAsmInstruction.h"

class SgAsmArmv8Instruction : public SgAsmInstruction {
public:

/*! \brief returns a string representing the class name */
virtual std::string class_name() const;

/*! \brief returns new style SageIII enum values */
virtual VariantT variantT() const; // MS: new variant used in tree traversal

/*! \brief static variant value */
enum {
static_variant = V_SgAsmArmv8Instruction
};

/* the generated cast function */
/*! \brief Casts pointer from base class to derived class */
friend SgAsmArmv8Instruction *isSgAsmArmv8Instruction( SgNode * s );

/*! \brief Casts pointer from base class to derived class (for const pointers) */
friend const SgAsmArmv8Instruction *isSgAsmArmv8Instruction(const SgNode *s);

public:
ARMv8InstructionKind get_kind() const;

void set_kind(ARMv8InstructionKind kind);

public:
virtual ~SgAsmArmv8Instruction();


public:
SgAsmArmv8Instruction(rose_addr_t address = 0, std::string mnemonic = "",
ARMv8InstructionKind kind = rose_aarch64_op_INVALID);


protected:
// Start of memberFunctionString
ARMv8InstructionKind p_kind;

// End of memberFunctionString

};

#endif

0 comments on commit 26a67de

Please sign in to comment.