From f4c17f6f824d71596b7b7519a652cf74670a4089 Mon Sep 17 00:00:00 2001 From: MITSUNARI Shigeo Date: Thu, 19 May 2016 07:06:17 +0900 Subject: [PATCH] add add/sub/shl --- src/gen.cpp | 30 ++++++++++- src/llvm_gen.hpp | 127 +++++++++++++++++++++++++++++++++-------------- 2 files changed, 119 insertions(+), 38 deletions(-) diff --git a/src/gen.cpp b/src/gen.cpp index 8f72724..b03850a 100644 --- a/src/gen.cpp +++ b/src/gen.cpp @@ -8,6 +8,7 @@ struct OnceCode : public mcl::Generator { Function mulUU; Function extractHigh; Function mulPos; + Function makeNIST_P192; void gen_mulUU() { @@ -55,7 +56,31 @@ struct OnceCode : public mcl::Generator { ret(xy); endFunc(); } - void gen(uint32_t unit, uint32_t bit) + void gen_makeNIST_P192() + { + resetGlobalIdx(); + Operand p0(Int, 64); + Operand p1(Int, 64); + Operand p2(Int, 64); + Operand _0 = makeImm(64, 0); + Operand _1 = makeImm(64, 1); + Operand _2 = makeImm(64, 2); + makeNIST_P192 = Function("makeNIST_P192", Operand()); + beginFunc(makeNIST_P192); + p0 = sub(_0, _1); + p1 = sub(_0, _2); + p2 = sub(_0, _1); + p0 = zext(p0, 192); + p1 = zext(p1, 192); + p2 = zext(p2, 192); + p1 = shl(p1, 64); + p2 = shl(p2, 128); + p0 = add(p0, p1); + p0 = add(p0, p2); + ret(p0); + endFunc(); + } + void run(uint32_t unit, uint32_t bit) { this->unit = unit; this->bit = bit; @@ -64,6 +89,7 @@ struct OnceCode : public mcl::Generator { gen_mulUU(); gen_extractHigh(); gen_mulPos(); + gen_makeNIST_P192(); } }; @@ -72,7 +98,7 @@ int main() try { OnceCode c; - c.gen(64, 256); + c.run(64, 256); } catch (std::exception& e) { printf("ERR %s\n", e.what()); return 1; diff --git a/src/llvm_gen.hpp b/src/llvm_gen.hpp index 501a4d3..4f2d1ac 100644 --- a/src/llvm_gen.hpp +++ b/src/llvm_gen.hpp @@ -103,15 +103,21 @@ struct Generator { } Eval zext(const Operand& x, uint32_t size); Eval mul(const Operand& x, const Operand& y); + Eval add(const Operand& x, const Operand& y); + Eval sub(const Operand& x, const Operand& y); void ret(const Operand& r); Eval lshr(const Operand& x, uint32_t size); + Eval shl(const Operand& x, uint32_t size); Eval trunc(const Operand& x, uint32_t size); Eval getelementptr(const Operand& p, const Operand& i); Eval load(const Operand& p); + Eval call(const Function& f); Eval call(const Function& f, const Operand& op1); Eval call(const Function& f, const Operand& op1, const Operand& op2); Eval call(const Function& f, const Operand& op1, const Operand& op2, const Operand& op3); Eval call(const Function& f, const Operand& op1, const Operand& op2, const Operand& op3, const Operand& op4); + + static inline Operand makeImm(uint32_t bit, uint64_t imm); }; struct Generator::Operand { @@ -148,9 +154,8 @@ struct Generator::Operand { default: return "void"; case Int: - return getType() + " " + getName(); case Imm: - return cybozu::itoa(imm); + return getType() + " " + getName(); } } std::string getType() const @@ -160,6 +165,7 @@ struct Generator::Operand { default: return ""; case Int: + case Imm: s = std::string("i") + cybozu::itoa(bit); break; } @@ -174,14 +180,25 @@ struct Generator::Operand { default: return ""; case Int: - std::string str("%"); - str += name; - if (idx > 0) str += "_" + cybozu::itoa(idx); - return str; + { + std::string str("%"); + str += name; + if (idx > 0) str += "_" + cybozu::itoa(idx); + return str; + } + case Imm: + return cybozu::itoa(imm); } } }; +inline Generator::Operand Generator::makeImm(uint32_t bit, uint64_t imm) +{ + Generator::Operand v(Generator::Imm, bit); + v.imm = imm; + return v; +} + struct Generator::Eval { std::string s; Generator::Operand op; @@ -220,6 +237,9 @@ struct Generator::Function { OperandVec opv; bool isPrivate; explicit Function(const std::string& name = "") : name(name), isPrivate(false) {} + Function(const std::string& name, const Operand& ret) + : name(name), ret(ret), isPrivate(false) { + } Function(const std::string& name, const Operand& ret, const Operand& op1) : name(name), ret(ret), isPrivate(false) { opv.push_back(op1); @@ -263,6 +283,52 @@ struct Generator::Function { } }; +namespace impl { + +inline Generator::Eval callSub(const Generator::Function& f, const Generator::Operand **opTbl, size_t opNum) +{ + if (f.opv.size() != opNum) throw cybozu::Exception("impl:callSub:bad num of arg") << f.opv.size() << opNum; + if (f.name.empty()) throw cybozu::Exception("impl:callSub:no name"); + Generator::Eval e; + e.op = f.ret; + e.s = "call "; + e.s += f.ret.getType(); + e.s += " @" + f.name + "("; + for (size_t i = 0; i < opNum; i++) { + if (i > 0) { + e.s += ", "; + } + e.s += opTbl[i]->toStr(); + } + e.s += ")"; + return e; +} + +inline Generator::Eval aluSub(const char *name, const Generator::Operand& x, const Generator::Operand& y) +{ + if (x.bit != y.bit) throw cybozu::Exception("Generator:aluSub:bad size") << name << x.bit << y.bit; + Generator::Eval e; + e.op.type = Generator::Int; + e.op.bit = x.bit; + e.op.name = x.name; + e.s = name; + e.s += " "; + e.s += x.toStr() + ", " + y.getName(); + return e; +} + +inline Generator::Eval shiftSub(const char *name, const Generator::Operand& x, uint32_t size) +{ + Generator::Eval e; + e.op = x; + e.s = name; + e.s += " "; + e.s += x.toStr() + ", " + cybozu::itoa(size); + return e; +} + +} // mcl::impl + inline void Generator::beginFunc(const Generator::Function& f) { put(f.toStr() + "\n{"); @@ -281,12 +347,17 @@ 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) { - if (x.bit != y.bit) throw cybozu::Exception("Generator:mul:bad size") << x.bit << y.bit; - Eval e; - e.op = x; - e.s = "mul "; - e.s += x.toStr() + ", " + y.getName(); - return e; + return impl::aluSub("mul", x, y); +} + +inline Generator::Eval Generator::add(const Generator::Operand& x, const Generator::Operand& y) +{ + return impl::aluSub("add", x, y); +} + +inline Generator::Eval Generator::sub(const Generator::Operand& x, const Generator::Operand& y) +{ + return impl::aluSub("sub", x, y); } inline void Generator::ret(const Generator::Operand& x) @@ -297,11 +368,12 @@ inline void Generator::ret(const Generator::Operand& x) 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; + return impl::shiftSub("lshr", x, size); +} + +inline Generator::Eval Generator::shl(const Generator::Operand& x, uint32_t size) +{ + return impl::shiftSub("shl", x, size); } inline Generator::Eval Generator::trunc(const Generator::Operand& x, uint32_t size) @@ -334,26 +406,9 @@ inline Generator::Eval Generator::load(const Generator::Operand& p) return e; } -namespace impl { - -static inline Generator::Eval callSub(const Generator::Function& f, const Generator::Operand **opTbl, size_t opNum) +inline Generator::Eval Generator::call(const Generator::Function& f) { - if (f.opv.size() != opNum) throw cybozu::Exception("implcallSub:bad num of arg") << f.opv.size() << opNum; - Generator::Eval e; - e.op = f.ret; - e.s = "call "; - e.s += f.ret.getType(); - e.s += " @" + f.name + "("; - for (size_t i = 0; i < opNum; i++) { - if (i > 0) { - e.s += ", "; - } - e.s += opTbl[i]->toStr(); - } - e.s += ")"; - return e; -} - + return impl::callSub(f, 0, 0); } inline Generator::Eval Generator::call(const Generator::Function& f, const Generator::Operand& op1)