1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
#pragma once
#include "FnCall.h"
#include "../Transform.h"
#include "../OpTable.h"
#include "../Reg.h"
#include "../Instr.h"
#include "Core/Array.h"
namespace code {
namespace x64 {
STORM_PKG(core.asm.x64);
class Arena;
/**
* Transform that removes invalid or otherwise non-supported OP-codes, replacing them with
* an equivalent sequence of supported OP-codes. For example:
* - memory-memory operands
* (Note: references and object references are stored in memory, and therefore count as a memory operand!)
* - immediate values that require 64 bits (need to be stored in memory as well)
*/
class RemoveInvalid : public Transform {
STORM_CLASS;
public:
STORM_CTOR RemoveInvalid(const Arena *arena);
// Start transform.
virtual void STORM_FN before(Listing *dest, Listing *src);
// Transform a single instruction.
virtual void STORM_FN during(Listing *dest, Listing *src, Nat id);
// Finalize transform.
virtual void STORM_FN after(Listing *dest, Listing *src);
private:
// Arena for platform specific concerns.
const Arena *arena;
// Used registers for each line.
Array<RegSet *> *used;
// Remember all 'large' constants that need to be stored at the end of the code section.
Array<Operand> *large;
// Remember all parameters that are stored indirectly.
// Note: used as a set, but since we expect it to contain few elements, this is likely faster.
Array<Nat> *indirectParams;
// Label to the start of the large constants section.
Label lblLarge;
// Extract any large numbers from an instruction.
Instr *extractNumbers(Instr *i);
// Remove any references to indirect parameters.
Instr *extractIndirectParams(Listing *dest, Instr *i, Nat line);
// Load floating-point register.
Reg loadFpRegister(Listing *dest, const Operand &op, Nat line);
Operand loadFpRegisterOrMemory(Listing *dest, const Operand &op, Nat line);
// Parameters for an upcoming 'fnCall' instruction.
Array<ParamInfo> *params;
// Current active block. We need that for introducing blocks inside the 'fnCall' transform.
Block currentBlock;
// Signature for the table of transform functions.
typedef void (RemoveInvalid::*TransformFn)(Listing *dest, Instr *instr, Nat line);
// Transform table.
static const OpEntry<TransformFn> transformMap[];
// Check if a variable refers to an indirect parameter.
bool isIndirectParam(Listing *l, Var var);
bool isIndirectParam(Listing *l, Operand op);
// Generic transform function for instructions using a generic two-op immReg form.
void immRegTfm(Listing *dest, Instr *instr, Nat line);
// Generic transform for instructions requiring their dest operand to be a register.
void destRegWTfm(Listing *dest, Instr *instr, Nat line);
void destRegRwTfm(Listing *dest, Instr *instr, Nat line);
// Generic transform for floating point operations.
void fpInstrTfm(Listing *dest, Instr *instr, Nat line);
// Function calls.
void fnParamTfm(Listing *dest, Instr *instr, Nat line);
void fnParamRefTfm(Listing *dest, Instr *instr, Nat line);
void fnCallTfm(Listing *dest, Instr *instr, Nat line);
void fnCallRefTfm(Listing *dest, Instr *instr, Nat line);
// Keep track of the current part.
void prologTfm(Listing *dest, Instr *instr, Nat line);
void beginBlockTfm(Listing *dest, Instr *instr, Nat line);
void endBlockTfm(Listing *dest, Instr *instr, Nat line);
// Other transforms.
void shlTfm(Listing *dest, Instr *instr, Nat line);
void shrTfm(Listing *dest, Instr *instr, Nat line);
void sarTfm(Listing *dest, Instr *instr, Nat line);
void idivTfm(Listing *dest, Instr *instr, Nat line);
void imodTfm(Listing *dest, Instr *instr, Nat line);
void udivTfm(Listing *dest, Instr *instr, Nat line);
void umodTfm(Listing *dest, Instr *instr, Nat line);
void fnegTfm(Listing *dest, Instr *instr, Nat line);
void fcastiTfm(Listing *dest, Instr *instr, Nat line);
void fcastuTfm(Listing *dest, Instr *instr, Nat line);
void icastfTfm(Listing *dest, Instr *instr, Nat line);
void ucastfTfm(Listing *dest, Instr *instr, Nat line);
};
}
}
|