add lhsr, trunc

dev
MITSUNARI Shigeo 9 years ago
parent 941a728481
commit 237ce0e369
  1. 37
      src/gen.cpp
  2. 116
      src/llvm_gen.hpp

@ -1,21 +1,38 @@
#include "llvm_gen.hpp" #include "llvm_gen.hpp"
struct Code : public mcl::Generator { struct OnceCode : public mcl::Generator {
uint32_t unit2;
Function gen_mulUU() Function gen_mulUU()
{ {
Operand z(Int, unit * 2); resetGlobalIdx();
Operand z(Int, unit2);
Operand x(Int, unit); Operand x(Int, unit);
Operand y(Int, unit); Operand y(Int, unit);
Function mulUU("mulUU", z, x, y); Function mulUU("mulUU", z, x, y);
beginFunc(mulUU); beginFunc(mulUU);
x = zext(x, unit * 2); x = zext(x, unit2);
y = zext(y, unit * 2); y = zext(y, unit2);
z= mul(x, y); z= mul(x, y);
ret(z); ret(z);
endFunc(); endFunc();
return mulUU; return mulUU;
} }
Function gen_extractHigh()
{
resetGlobalIdx();
Operand z(Int, unit);
Operand x(Int, unit2);
Function extractHigh("extractHigh", z, x);
extractHigh.setPrivate();
beginFunc(extractHigh);
x = lshr(x, unit);
z = trunc(x, unit);
ret(z);
endFunc();
return extractHigh;
}
Function gen_mulPv(int bu) Function gen_mulPv(int bu)
{ {
Operand z(Int, bu); Operand z(Int, bu);
@ -26,12 +43,13 @@ struct Code : public mcl::Generator {
endFunc(); endFunc();
return mulPv; return mulPv;
} }
Code() void gen(uint32_t unit, uint32_t bit)
{ {
using namespace mcl; set(unit, bit);
const int bu = unit + bit; unit2 = unit * 2;
Function mulUU = gen_mulUU(); Function mulUU = gen_mulUU();
Function mulPv = gen_mulPv(bu); Function extractHigh = gen_extractHigh();
// Function mulPv = gen_mulPv(bu);
} }
}; };
@ -39,7 +57,8 @@ struct Code : public mcl::Generator {
int main() int main()
try try
{ {
Code c; OnceCode c;
c.gen(64, 256);
} catch (std::exception& e) { } catch (std::exception& e) {
printf("ERR %s\n", e.what()); printf("ERR %s\n", e.what());
return 1; return 1;

@ -10,18 +10,58 @@
#include <vector> #include <vector>
#include <cybozu/exception.hpp> #include <cybozu/exception.hpp>
#include <cybozu/itoa.hpp> #include <cybozu/itoa.hpp>
#include <stdio.h>
namespace mcl { namespace mcl {
namespace impl {
struct File {
FILE *fp;
File() : fp(stdout) {}
~File() { if (fp != stdout) fclose(fp); }
void open(const std::string& file)
{
#ifdef _MSC_VER
bool isOK = fopen_s(&fp, file.c_str(), "wb") != 0;
#else
fp = fopen(file.c_str(), "wb");
bool isOK = fp != NULL;
#endif
if (!isOK) throw cybozu::Exception("File:open") << file;
}
void write(const std::string& str)
{
int ret = fprintf(fp, "%s\n", str.c_str());
if (ret < 0) {
throw cybozu::Exception("File:write") << str;
}
}
};
template<size_t dummy=0>
struct Param {
static File f;
};
template<size_t dummy>
File Param<dummy>::f;
} // mcl::impl
struct Generator { struct Generator {
int unit; uint32_t unit;
int N; uint32_t bit;
int bit; uint32_t N;
Generator() Generator() : unit(0), bit(0), N(0) {}
: unit(sizeof(uint64_t) * 8) void set(uint32_t unit, uint32_t bit)
, N(4)
, bit(unit * N)
{ {
this->unit = unit;
this->bit = bit;
this->N = bit / unit;
}
void open(const std::string& file)
{
impl::Param<>::f.open(file);
} }
enum Type { enum Type {
Void = 0, Void = 0,
@ -32,14 +72,23 @@ struct Generator {
struct Operand; struct Operand;
struct Function; struct Function;
struct Eval; struct Eval;
static inline std::string getGlobalName() static inline int& getGlobalIdx()
{ {
static int globalIdx = 0; static int globalIdx = 0;
return std::string("reg") + cybozu::itoa(globalIdx++); return globalIdx;
}
static inline void resetGlobalIdx()
{
getGlobalIdx() = 0;
}
static inline std::string getGlobalName()
{
int& idx = getGlobalIdx();
return std::string("reg") + cybozu::itoa(idx++);
} }
static inline void put(const std::string& str) static inline void put(const std::string& str)
{ {
printf("%s\n", str.c_str()); impl::Param<>::f.write(str);
} }
void beginFunc(const Function& f); void beginFunc(const Function& f);
void endFunc() void endFunc()
@ -49,6 +98,8 @@ struct Generator {
Eval zext(const Operand& x, uint32_t size); Eval zext(const Operand& x, uint32_t size);
Eval mul(const Operand& x, const Operand& y); Eval mul(const Operand& x, const Operand& y);
void ret(const Operand& r); void ret(const Operand& r);
Eval lshr(const Operand& x, uint32_t size);
Eval trunc(const Operand& x, uint32_t size);
}; };
struct Generator::Operand { struct Generator::Operand {
@ -150,32 +201,42 @@ struct Generator::Function {
std::string name; std::string name;
Generator::Operand ret; Generator::Operand ret;
OperandVec opv; OperandVec opv;
explicit Function(const std::string& name = "") : name(name) {} bool isPrivate;
explicit Function(const std::string& name = "") : name(name), isPrivate(false) {}
Function(const std::string& name, const Operand& ret, const Operand& op1) Function(const std::string& name, const Operand& ret, const Operand& op1)
: name(name), ret(ret) { : name(name), ret(ret), isPrivate(false) {
opv.push_back(op1); opv.push_back(op1);
} }
Function(const std::string& name, const Operand& ret, const Operand& op1, const Operand& op2) Function(const std::string& name, const Operand& ret, const Operand& op1, const Operand& op2)
: name(name), ret(ret) { : name(name), ret(ret), isPrivate(false) {
opv.push_back(op1); opv.push_back(op1);
opv.push_back(op2); opv.push_back(op2);
} }
Function(const std::string& name, const Operand& ret, const Operand& op1, const Operand& op2, const Operand& op3) Function(const std::string& name, const Operand& ret, const Operand& op1, const Operand& op2, const Operand& op3)
: name(name), ret(ret) { : name(name), ret(ret), isPrivate(false) {
opv.push_back(op1); opv.push_back(op1);
opv.push_back(op2); opv.push_back(op2);
opv.push_back(op3); opv.push_back(op3);
} }
Function(const std::string& name, const Operand& ret, const Operand& op1, const Operand& op2, const Operand& op3, const Operand& op4) Function(const std::string& name, const Operand& ret, const Operand& op1, const Operand& op2, const Operand& op3, const Operand& op4)
: name(name), ret(ret) { : name(name), ret(ret), isPrivate(false) {
opv.push_back(op1); opv.push_back(op1);
opv.push_back(op2); opv.push_back(op2);
opv.push_back(op3); opv.push_back(op3);
opv.push_back(op4); opv.push_back(op4);
} }
void setPrivate()
{
isPrivate = true;
}
std::string toStr() const std::string toStr() const
{ {
std::string str = std::string("define ") + ret.getType() + " @" + name + "("; std::string str = std::string("define ");
if (isPrivate) {
str += "private ";
}
str += ret.getType();
str += " @" + name + "(";
for (size_t i = 0; i < opv.size(); i++) { for (size_t i = 0; i < opv.size(); i++) {
if (i > 0) str += ", "; if (i > 0) str += ", ";
str += opv[i].toStr(); str += opv[i].toStr();
@ -192,7 +253,7 @@ inline void Generator::beginFunc(const Generator::Function& f)
inline Generator::Eval Generator::zext(const Generator::Operand& x, uint32_t size) inline Generator::Eval Generator::zext(const Generator::Operand& x, uint32_t size)
{ {
if (x.bit >= size) throw cybozu::Exception("zext:bad size") << x.bit << size; if (x.bit >= size) throw cybozu::Exception("Generator:zext:bad size") << x.bit << size;
Eval e; Eval e;
e.op = x; e.op = x;
e.op.bit = size; e.op.bit = size;
@ -203,7 +264,7 @@ inline Generator::Eval Generator::zext(const Generator::Operand& x, uint32_t siz
inline Generator::Eval Generator::mul(const Generator::Operand& x, const Generator::Operand& y) inline Generator::Eval Generator::mul(const Generator::Operand& x, const Generator::Operand& y)
{ {
if (x.bit != y.bit) throw cybozu::Exception("mul:bad size") << x.bit << y.bit; if (x.bit != y.bit) throw cybozu::Exception("Generator:mul:bad size") << x.bit << y.bit;
Eval e; Eval e;
e.op = x; e.op = x;
e.s = "mul "; e.s = "mul ";
@ -211,6 +272,25 @@ inline Generator::Eval Generator::mul(const Generator::Operand& x, const Generat
return e; return e;
} }
inline Generator::Eval Generator::lshr(const Generator::Operand& x, uint32_t size)
{
Eval e;
e.op = x;
e.s = "lshr ";
e.s += x.toStr() + ", " + cybozu::itoa(size);
return e;
}
inline Generator::Eval Generator::trunc(const Generator::Operand& x, uint32_t size)
{
Eval e;
e.op = x;
e.op.bit = size;
e.s = "trunc ";
e.s += x.toStr() + " to i" + cybozu::itoa(size);
return e;
}
inline void Generator::ret(const Generator::Operand& x) inline void Generator::ret(const Generator::Operand& x)
{ {
std::string s = "ret " + x.toStr(); std::string s = "ret " + x.toStr();

Loading…
Cancel
Save