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 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;

@ -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;
}
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)

Loading…
Cancel
Save