add add/sub/shl

dev
MITSUNARI Shigeo 9 years ago
parent db2f497fa2
commit f4c17f6f82
  1. 30
      src/gen.cpp
  2. 119
      src/llvm_gen.hpp

@ -8,6 +8,7 @@ struct OnceCode : public mcl::Generator {
Function mulUU; Function mulUU;
Function extractHigh; Function extractHigh;
Function mulPos; Function mulPos;
Function makeNIST_P192;
void gen_mulUU() void gen_mulUU()
{ {
@ -55,7 +56,31 @@ struct OnceCode : public mcl::Generator {
ret(xy); ret(xy);
endFunc(); 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->unit = unit;
this->bit = bit; this->bit = bit;
@ -64,6 +89,7 @@ struct OnceCode : public mcl::Generator {
gen_mulUU(); gen_mulUU();
gen_extractHigh(); gen_extractHigh();
gen_mulPos(); gen_mulPos();
gen_makeNIST_P192();
} }
}; };
@ -72,7 +98,7 @@ int main()
try try
{ {
OnceCode c; OnceCode c;
c.gen(64, 256); c.run(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;

@ -103,15 +103,21 @@ 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);
Eval add(const Operand& x, const Operand& y);
Eval sub(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 lshr(const Operand& x, uint32_t size);
Eval shl(const Operand& x, uint32_t size);
Eval trunc(const Operand& x, uint32_t size); Eval trunc(const Operand& x, uint32_t size);
Eval getelementptr(const Operand& p, const Operand& i); Eval getelementptr(const Operand& p, const Operand& i);
Eval load(const Operand& p); 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);
Eval call(const Function& f, const Operand& op1, const Operand& op2); 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);
Eval call(const Function& f, const Operand& op1, const Operand& op2, const Operand& op3, const Operand& op4); 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 { struct Generator::Operand {
@ -148,9 +154,8 @@ struct Generator::Operand {
default: default:
return "void"; return "void";
case Int: case Int:
return getType() + " " + getName();
case Imm: case Imm:
return cybozu::itoa(imm); return getType() + " " + getName();
} }
} }
std::string getType() const std::string getType() const
@ -160,6 +165,7 @@ struct Generator::Operand {
default: default:
return ""; return "";
case Int: case Int:
case Imm:
s = std::string("i") + cybozu::itoa(bit); s = std::string("i") + cybozu::itoa(bit);
break; break;
} }
@ -174,14 +180,25 @@ struct Generator::Operand {
default: default:
return ""; return "";
case Int: case Int:
{
std::string str("%"); std::string str("%");
str += name; str += name;
if (idx > 0) str += "_" + cybozu::itoa(idx); if (idx > 0) str += "_" + cybozu::itoa(idx);
return str; 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 { struct Generator::Eval {
std::string s; std::string s;
Generator::Operand op; Generator::Operand op;
@ -220,6 +237,9 @@ struct Generator::Function {
OperandVec opv; OperandVec opv;
bool isPrivate; bool isPrivate;
explicit Function(const std::string& name = "") : name(name), isPrivate(false) {} 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) Function(const std::string& name, const Operand& ret, const Operand& op1)
: name(name), ret(ret), isPrivate(false) { : name(name), ret(ret), isPrivate(false) {
opv.push_back(op1); 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) inline void Generator::beginFunc(const Generator::Function& f)
{ {
put(f.toStr() + "\n{"); 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) 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; return impl::aluSub("mul", x, y);
Eval e; }
e.op = x;
e.s = "mul "; inline Generator::Eval Generator::add(const Generator::Operand& x, const Generator::Operand& y)
e.s += x.toStr() + ", " + y.getName(); {
return e; 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) 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) inline Generator::Eval Generator::lshr(const Generator::Operand& x, uint32_t size)
{ {
Eval e; return impl::shiftSub("lshr", x, size);
e.op = x; }
e.s = "lshr ";
e.s += x.toStr() + ", " + cybozu::itoa(size); inline Generator::Eval Generator::shl(const Generator::Operand& x, uint32_t size)
return e; {
return impl::shiftSub("shl", x, size);
} }
inline Generator::Eval Generator::trunc(const Generator::Operand& x, uint32_t 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; return e;
} }
namespace impl { inline Generator::Eval Generator::call(const Generator::Function& f)
static inline Generator::Eval callSub(const Generator::Function& f, const Generator::Operand **opTbl, size_t opNum)
{ {
if (f.opv.size() != opNum) throw cybozu::Exception("implcallSub:bad num of arg") << f.opv.size() << opNum; return impl::callSub(f, 0, 0);
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 Generator::call(const Generator::Function& f, const Generator::Operand& op1) inline Generator::Eval Generator::call(const Generator::Function& f, const Generator::Operand& op1)

Loading…
Cancel
Save