rx2c.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. import random
  2. import sys
  3. import os
  4. PROGRAM_SIZE = 512
  5. INSTRUCTION_COUNT = 1024 * 1024
  6. INSTRUCTION_WEIGHTS = [
  7. ("ADD_64", 16),
  8. ("ADD_32", 8),
  9. ("SUB_64", 16),
  10. ("SUB_32", 8),
  11. ("MUL_64", 7),
  12. ("MULH_64", 7),
  13. ("MUL_32", 7),
  14. ("IMUL_32", 7),
  15. ("IMULH_64", 7),
  16. ("DIV_64", 1),
  17. ("IDIV_64", 1),
  18. ("AND_64", 4),
  19. ("AND_32", 3),
  20. ("OR_64", 4),
  21. ("OR_32", 3),
  22. ("XOR_64", 4),
  23. ("XOR_32", 3),
  24. ("SHL_64", 6),
  25. ("SHR_64", 6),
  26. ("SAR_64", 6),
  27. ("ROL_64", 9),
  28. ("ROR_64", 9),
  29. ("FADD", 22),
  30. ("FSUB", 22),
  31. ("FMUL", 22),
  32. ("FDIV", 8),
  33. ("FSQRT", 6),
  34. ("FROUND", 2),
  35. ("CALL", 17),
  36. ("RET", 15),
  37. ]
  38. def genBytes(count):
  39. return ', '.join(str(random.getrandbits(8)) for i in range(count))
  40. class OperandType:
  41. INT32 = 0
  42. UINT32 = 1
  43. INT64 = 2
  44. UINT64 = 3
  45. FLOAT = 4
  46. SHIFT = 5
  47. def declareType(type):
  48. converters = {
  49. 0: "int32_t",
  50. 1: "uint32_t",
  51. 2: "int64_t",
  52. 3: "uint64_t",
  53. 4: "double",
  54. 5: "int32_t"
  55. }
  56. return converters.get(type)
  57. def toSigned32(x):
  58. return x - ((x & 0x80000000) << 1)
  59. def toSigned64(x):
  60. return x - ((x & 0x8000000000000000) << 1)
  61. def immediateTo(symbol, type):
  62. converters = {
  63. 0: toSigned32(symbol.imm1),
  64. 1: symbol.imm1,
  65. 2: toSigned32(symbol.imm1),
  66. 3: symbol.imm1,
  67. 4: float(toSigned32(symbol.imm1) << 32),
  68. 5: symbol.imm0 & 63
  69. }
  70. return repr(converters.get(type))
  71. def registerTo(expr, type):
  72. converters = {
  73. 0: "(int64_t){0}",
  74. 1: "{0}",
  75. 2: "(int64_t){0}",
  76. 3: "{0}",
  77. 4: "{0}",
  78. 5: "({0} & 63)"
  79. }
  80. return converters.get(type).format(expr)
  81. def registerFrom(num, type):
  82. converters = {
  83. 0: "r{0}",
  84. 1: "r{0}",
  85. 2: "r{0}",
  86. 3: "r{0}",
  87. 4: "((convertible_t)f{0}).u64",
  88. 5: "r{0}"
  89. }
  90. return converters.get(type).format(num)
  91. def convertibleTo(expr, type):
  92. converters = {
  93. 0: "{0}.i32",
  94. 1: "{0}.u32",
  95. 2: "{0}.i64",
  96. 3: "{0}.u64",
  97. 4: "(double){0}.i64",
  98. 5: "({0}.u64 & 63)"
  99. }
  100. return converters.get(type).format(expr)
  101. def convertibleFrom(expr, type):
  102. converters = {
  103. 0: "{0}.i32",
  104. 1: "{0}.u32",
  105. 2: "{0}.i64",
  106. 3: "{0}.u64",
  107. 4: "{0}.f64",
  108. 5: "({0}.u64 & 63)"
  109. }
  110. return converters.get(type).format(expr)
  111. def getRegister(num, type):
  112. registers = {
  113. 0: "r{0}",
  114. 1: "r{0}",
  115. 2: "r{0}",
  116. 3: "r{0}",
  117. 4: "f{0}",
  118. 5: "r{0}"
  119. }
  120. return registers.get(type).format(num)
  121. def writeInitialValues(file):
  122. file.write("#ifdef RAM\n")
  123. file.write("\tmmu.buffer = (char*)_mm_malloc(DRAM_SIZE, 16);\n")
  124. file.write("\tif(!mmu.buffer) {\n")
  125. file.write('\t\tprintf("DRAM buffer allocation failed\\n");\n')
  126. file.write("\t\treturn 1;\n")
  127. file.write("\t}\n")
  128. file.write('\tprintf("Initializing DRAM buffer...\\n");\n')
  129. file.write("\taesInitialize((__m128i*)aesKey, (__m128i*)aesSeed, (__m128i*)mmu.buffer, DRAM_SIZE);\n")
  130. file.write("#endif\n")
  131. file.write("\tclock_t clockStart = clock(), clockEnd;\n")
  132. for i in range(8):
  133. file.write("\tr{0} = *(uint64_t*)(aesSeed + {1});\n".format(i, i * 8))
  134. for i in range(8):
  135. file.write("\tf{0} = *(int64_t*)(aesSeed + {1});\n".format(i, 64 + i * 8))
  136. file.write("\taesInitialize((__m128i*)aesKey, (__m128i*)aesSeed, (__m128i*)scratchpad, SCRATCHPAD_SIZE);\n")
  137. file.write("\tmmu.ma = *(addr_t*)(aesKey + 8) & ~7U;\n")
  138. file.write("#ifdef PRNTADDR\n")
  139. file.write('\tprintf("DRAM address = %#010x\\n", mmu.ma);\n')
  140. file.write("#endif\n")
  141. file.write("\tmmu.mx = 0;\n")
  142. file.write("\tsp = 0;\n")
  143. file.write("\tic = {0};\n".format(INSTRUCTION_COUNT))
  144. file.write("\tmxcsr = (_mm_getcsr() | _MM_FLUSH_ZERO_ON) & ~_MM_ROUND_MASK; //flush denormals to zero, round to nearest\n")
  145. file.write("\t_mm_setcsr(mxcsr);\n")
  146. def writeEpilog(file):
  147. file.write("\tend:\n")
  148. file.write("\t\tclockEnd = clock();\n")
  149. for i in range(8):
  150. file.write('\t\tprintf("r{0} = %-36" PRIu64 " f{0} = %g\\n", r{0}, f{0});\n'.format(i))
  151. file.write(("\t\tuint64_t spadsum = 0;\n"
  152. "\t\tfor(int i = 0; i < SCRATCHPAD_LENGTH; ++i) {\n"
  153. "\t\t spadsum += scratchpad[i].u64;\n"
  154. "\t\t}\n"
  155. '\t\tprintf("scratchpad sum = %" PRIu64 "\\n", spadsum);\n'
  156. '\t\tprintf("runtime: %f\\n", (clockEnd - clockStart) / (double)CLOCKS_PER_SEC);\n'
  157. "#ifdef RAM\n"
  158. "\t\t_mm_free((void*)mmu.buffer);\n"
  159. "#endif\n"))
  160. file.write("\t\treturn 0;")
  161. file.write("}")
  162. def writeCommon(file, i, symbol, type, name):
  163. file.write("\ti_{0}: {{ //{1}\n".format(i, name))
  164. file.write("\t\tif(0 == ic--) goto end;\n")
  165. file.write("\t\tr{0} ^= {1};\n".format(symbol.rega, symbol.addr0))
  166. file.write("\t\taddr_t addr = r{0};\n".format(symbol.rega))
  167. def readA(symbol, type):
  168. location = {
  169. 0: "readDram(&mmu, addr)",
  170. 1: "readDram(&mmu, addr)",
  171. 2: "readDram(&mmu, addr)",
  172. 3: "readDram(&mmu, addr)",
  173. 4: "SCRATCHPAD_256K(addr)",
  174. 5: "SCRATCHPAD_16K(addr)",
  175. 6: "SCRATCHPAD_16K(addr)",
  176. 7: "SCRATCHPAD_16K(addr)",
  177. }
  178. return convertibleTo(location.get(symbol.loca), type)
  179. def writeC(symbol, type):
  180. location = {
  181. 0: "SCRATCHPAD_256K(r{0} ^ {1})",
  182. 1: "SCRATCHPAD_16K(r{0} ^ {1})",
  183. 2: "SCRATCHPAD_16K(r{0} ^ {1})",
  184. 3: "SCRATCHPAD_16K(r{0} ^ {1})",
  185. 4: "",
  186. 5: "",
  187. 6: "",
  188. 7: ""
  189. }
  190. c = location.get(symbol.locc)
  191. if c == "":
  192. c = getRegister(symbol.regc, type)
  193. else:
  194. c = convertibleFrom(c.format(symbol.regc, symbol.addr1), type)
  195. return c
  196. def readB(symbol, type):
  197. if symbol.locb < 6:
  198. return registerTo(getRegister(symbol.regb, type), type)
  199. else:
  200. return immediateTo(symbol, type)
  201. class CodeSymbol:
  202. def __init__(self, qi):
  203. self.opcode = qi & 255
  204. self.loca = (qi >> 8) & 7
  205. self.rega = (qi >> 16) & 7
  206. self.locb = (qi >> 24) & 7
  207. self.regb = (qi >> 32) & 7
  208. self.locc = (qi >> 40) & 7
  209. self.regc = (qi >> 48) & 7
  210. self.imm0 = (qi >> 56) & 255
  211. self.addr0 = (qi >> 64) & 0xFFFFFFFF
  212. self.addr1 = self.imm1 = qi >> 96
  213. def writeOperation(file, i, symbol, type, name, op):
  214. writeCommon(file, i, symbol, type, name)
  215. file.write("\t\t{0} A = {1};\n".format(declareType(type), readA(symbol, type)))
  216. file.write("\t\t{0} B = {1};\n".format(declareType(type), readB(symbol, type)))
  217. file.write("\t\t{0} = A {1} B; }}\n".format(writeC(symbol, type), op))
  218. def write_ADD_64(file, i, symbol):
  219. writeOperation(file, i, symbol, OperandType.UINT64, 'ADD_64', '+');
  220. def write_ADD_32(file, i, symbol):
  221. writeOperation(file, i, symbol, OperandType.UINT32, 'ADD_32', '+');
  222. def write_SUB_64(file, i, symbol):
  223. writeOperation(file, i, symbol, OperandType.UINT64, 'SUB_64', '-');
  224. def write_SUB_32(file, i, symbol):
  225. writeOperation(file, i, symbol, OperandType.UINT32, 'SUB_32', '-');
  226. def write_MUL_64(file, i, symbol):
  227. writeOperation(file, i, symbol, OperandType.UINT64, 'MUL_64', '*');
  228. def write_MULH_64(file, i, symbol):
  229. type = OperandType.UINT64
  230. writeCommon(file, i, symbol, type, 'MULH_64')
  231. file.write("\t\t{0} A = {1};\n".format(declareType(type), readA(symbol, type)))
  232. file.write("\t\t{0} B = {1};\n".format(declareType(type), readB(symbol, type)))
  233. file.write("\t\t{0} = ((uint128_t)A * B) >> 64; }}\n".format(writeC(symbol, type)))
  234. def write_MUL_32(file, i, symbol):
  235. type = OperandType.UINT32
  236. writeCommon(file, i, symbol, type, 'MUL_32')
  237. file.write("\t\t{0} A = {1};\n".format(declareType(type), readA(symbol, type)))
  238. file.write("\t\t{0} B = {1};\n".format(declareType(type), readB(symbol, type)))
  239. file.write("\t\t{0} = (uint64_t)A * B; }}\n".format(writeC(symbol, OperandType.UINT64)))
  240. def write_IMUL_32(file, i, symbol):
  241. type = OperandType.INT32
  242. writeCommon(file, i, symbol, type, 'IMUL_32')
  243. file.write("\t\t{0} A = {1};\n".format(declareType(type), readA(symbol, type)))
  244. file.write("\t\t{0} B = {1};\n".format(declareType(type), readB(symbol, type)))
  245. file.write("\t\t{0} = (int64_t)A * B; }}\n".format(writeC(symbol, OperandType.INT64)))
  246. def write_IMULH_64(file, i, symbol):
  247. type = OperandType.INT64
  248. writeCommon(file, i, symbol, type, 'IMULH_64')
  249. file.write("\t\t{0} A = {1};\n".format(declareType(type), readA(symbol, type)))
  250. file.write("\t\t{0} B = {1};\n".format(declareType(type), readB(symbol, type)))
  251. file.write("\t\t{0} = ((int128_t)A * B) >> 64; }}\n".format(writeC(symbol, type)))
  252. def write_DIV_64(file, i, symbol):
  253. type = OperandType.UINT64
  254. writeCommon(file, i, symbol, type, 'DIV_64')
  255. file.write("\t\t{0} A = {1};\n".format(declareType(type), readA(symbol, type)))
  256. file.write("\t\t{0} B = {1};\n".format(declareType(OperandType.UINT32), readB(symbol, OperandType.UINT32)))
  257. file.write("\t\tif(B == 0) B = 1;\n".format(declareType(type), readB(symbol, type)))
  258. file.write("\t\t{0} = A / B; }}\n".format(writeC(symbol, type)))
  259. def write_IDIV_64(file, i, symbol):
  260. type = OperandType.INT64
  261. writeCommon(file, i, symbol, type, 'IDIV_64')
  262. file.write("\t\t{0} A = {1};\n".format(declareType(type), readA(symbol, type)))
  263. file.write("\t\t{0} B = {1};\n".format(declareType(OperandType.INT32), readB(symbol, OperandType.INT32)))
  264. file.write("\t\tif(B == 0) B = 1;\n".format(declareType(type), readB(symbol, type)))
  265. file.write("\t\t{0} = A / B; }}\n".format(writeC(symbol, type)))
  266. def write_AND_64(file, i, symbol):
  267. writeOperation(file, i, symbol, OperandType.UINT64, 'AND_64', '&');
  268. def write_AND_32(file, i, symbol):
  269. writeOperation(file, i, symbol, OperandType.UINT32, 'AND_32', '&');
  270. def write_OR_64(file, i, symbol):
  271. writeOperation(file, i, symbol, OperandType.UINT64, 'OR_64', '|');
  272. def write_OR_32(file, i, symbol):
  273. writeOperation(file, i, symbol, OperandType.UINT32, 'OR_32', '|');
  274. def write_XOR_64(file, i, symbol):
  275. writeOperation(file, i, symbol, OperandType.UINT64, 'XOR_64', '^');
  276. def write_XOR_32(file, i, symbol):
  277. writeOperation(file, i, symbol, OperandType.UINT32, 'XOR_32', '^');
  278. def write_SHL_64(file, i, symbol):
  279. type = OperandType.UINT64
  280. writeCommon(file, i, symbol, type, 'SHL_64')
  281. file.write("\t\t{0} A = {1};\n".format(declareType(type), readA(symbol, type)))
  282. file.write("\t\t{0} B = {1};\n".format(declareType(OperandType.SHIFT), readB(symbol, OperandType.SHIFT)))
  283. file.write("\t\t{0} = A << B; }}\n".format(writeC(symbol, type)))
  284. def write_SHR_64(file, i, symbol):
  285. type = OperandType.UINT64
  286. writeCommon(file, i, symbol, type, 'SHR_64')
  287. file.write("\t\t{0} A = {1};\n".format(declareType(type), readA(symbol, type)))
  288. file.write("\t\t{0} B = {1};\n".format(declareType(OperandType.SHIFT), readB(symbol, OperandType.SHIFT)))
  289. file.write("\t\t{0} = A >> B; }}\n".format(writeC(symbol, type)))
  290. def write_SAR_64(file, i, symbol):
  291. type = OperandType.INT64
  292. writeCommon(file, i, symbol, type, 'SAR_64')
  293. file.write("\t\t{0} A = {1};\n".format(declareType(type), readA(symbol, type)))
  294. file.write("\t\t{0} B = {1};\n".format(declareType(OperandType.SHIFT), readB(symbol, OperandType.SHIFT)))
  295. file.write("\t\t{0} = A >> B; }}\n".format(writeC(symbol, type)))
  296. def write_ROL_64(file, i, symbol):
  297. type = OperandType.UINT64
  298. writeCommon(file, i, symbol, type, 'ROL_64')
  299. file.write("\t\t{0} A = {1};\n".format(declareType(type), readA(symbol, type)))
  300. file.write("\t\t{0} B = {1};\n".format(declareType(OperandType.SHIFT), readB(symbol, OperandType.SHIFT)))
  301. file.write("\t\t{0} = __rolq(A, B); }}\n".format(writeC(symbol, type)))
  302. def write_ROR_64(file, i, symbol):
  303. type = OperandType.UINT64
  304. writeCommon(file, i, symbol, type, 'ROR_64')
  305. file.write("\t\t{0} A = {1};\n".format(declareType(type), readA(symbol, type)))
  306. file.write("\t\t{0} B = {1};\n".format(declareType(OperandType.SHIFT), readB(symbol, OperandType.SHIFT)))
  307. file.write("\t\t{0} = __rorq(A, B); }}\n".format(writeC(symbol, type)))
  308. def write_FADD(file, i, symbol):
  309. writeOperation(file, i, symbol, OperandType.FLOAT, 'FADD', '+');
  310. def write_FSUB(file, i, symbol):
  311. writeOperation(file, i, symbol, OperandType.FLOAT, 'FSUB', '-');
  312. def write_FMUL(file, i, symbol):
  313. writeOperation(file, i, symbol, OperandType.FLOAT, 'FMUL', '*');
  314. def write_FDIV(file, i, symbol):
  315. writeOperation(file, i, symbol, OperandType.FLOAT, 'FDIV', '/');
  316. def write_FSQRT(file, i, symbol):
  317. type = OperandType.FLOAT
  318. writeCommon(file, i, symbol, type, 'FSQRT')
  319. file.write("\t\t{0} A = fabs({1});\n".format(declareType(type), readA(symbol, type)))
  320. file.write("\t\t{0} = _mm_cvtsd_f64(_mm_sqrt_sd(_mm_setzero_pd(), _mm_load_pd(&A))); }}\n".format(writeC(symbol, type)))
  321. def write_FROUND(file, i, symbol):
  322. type = OperandType.FLOAT
  323. writeCommon(file, i, symbol, type, 'FROUND')
  324. file.write("\t\t{0} A = {1};\n".format(declareType(OperandType.INT64), readA(symbol, OperandType.INT64)))
  325. file.write("\t\t{0} = A;\n".format(writeC(symbol, type)))
  326. file.write("\t\t_mm_setcsr(mxcsr | ((uint32_t)(A << 13) & _MM_ROUND_MASK)); }\n")
  327. def write_CALL(file, i, symbol):
  328. type = OperandType.UINT64
  329. writeCommon(file, i, symbol, type, 'CALL')
  330. file.write("\t\t{0} A = {1};\n".format(declareType(type), readA(symbol, type)))
  331. if symbol.locb < 6:
  332. file.write("\t\tif((uint32_t)r{0} <= {1}) {{\n".format(symbol.regb, symbol.imm1))
  333. file.write("\t\t\tPUSH_VALUE(A);\n");
  334. file.write("\t\t\tPUSH_ADDRESS(&&i_{0});\n".format((i + 1) & (PROGRAM_SIZE - 1)));
  335. file.write("\t\t\tgoto i_{0};\n".format((i + 1 + (symbol.imm0 & ((PROGRAM_SIZE >> 2) - 1))) & (PROGRAM_SIZE - 1)));
  336. if symbol.locb < 6:
  337. file.write("\t\t}}\n\t\t{0} = A;".format(writeC(symbol, type)))
  338. file.write("\t\t}\n")
  339. def write_RET(file, i, symbol):
  340. type = OperandType.UINT64
  341. writeCommon(file, i, symbol, type, 'RET')
  342. file.write("\t\t{0} A = {1};\n".format(declareType(type), readA(symbol, type)))
  343. file.write("\t\tif(!STACK_IS_EMPTY()")
  344. if symbol.locb < 6:
  345. file.write(" && (uint32_t)r{0} <= {1}".format(symbol.regb, symbol.imm1))
  346. file.write(") {\n")
  347. file.write("\t\t\tvoid* target = POP_ADDRESS();\n")
  348. file.write("\t\t\tuint64_t C = POP_VALUE();\n")
  349. file.write("\t\t\t{0} = A ^ C;\n".format(writeC(symbol, type)))
  350. file.write("\t\t\tgoto *target;\n")
  351. file.write("\t\t}}\n\t\t{0} = A; }}\n".format(writeC(symbol, type)))
  352. opcodeMap = { }
  353. def buildOpcodeMap():
  354. functions = globals()
  355. totalWeight = 0;
  356. for instruction, weight in INSTRUCTION_WEIGHTS:
  357. func = functions['write_' + instruction]
  358. for i in range(weight):
  359. opcodeMap[totalWeight] = func
  360. totalWeight = totalWeight + 1
  361. assert totalWeight == 256
  362. def writeCode(file, i, symbol):
  363. opcodeMap.get(symbol.opcode)(file, i, symbol)
  364. def writeMain(file):
  365. file.write(('__attribute__((optimize("Os"))) int main() {\n'
  366. " register uint64_t r0, r1, r2, r3, r4, r5, r6, r7;\n"
  367. " register double f0, f1, f2, f3, f4, f5, f6, f7;\n"
  368. " register uint64_t ic, sp;\n"
  369. " stack_t stack[STACK_LENGTH];\n"
  370. " convertible_t scratchpad[SCRATCHPAD_LENGTH] __attribute__ ((aligned (16)));\n"
  371. " mmu_t mmu;\n"
  372. " uint32_t mxcsr;\n"
  373. ))
  374. def writeProlog(file):
  375. file.write(("#include <stdint.h>\n"
  376. "#include <time.h>\n"
  377. "#include <stdio.h>\n"
  378. "#include <x86intrin.h>\n"
  379. "#include <emmintrin.h>\n"
  380. "#include <wmmintrin.h>\n"
  381. "#include <math.h>\n"
  382. "#include <inttypes.h>\n"
  383. "typedef uint32_t addr_t;\n"
  384. "typedef unsigned __int128 uint128_t;\n"
  385. "typedef __int128 int128_t;\n"
  386. "typedef unsigned char byte;\n"
  387. "typedef union {\n"
  388. " double f64;\n"
  389. " int64_t i64;\n"
  390. " uint64_t u64;\n"
  391. " int32_t i32;\n"
  392. " uint32_t u32;\n"
  393. "} convertible_t;\n"
  394. "typedef union {\n"
  395. " uint64_t value;\n"
  396. " void* address;\n"
  397. "} stack_t;\n"
  398. "typedef struct {\n"
  399. " addr_t ma;\n"
  400. " addr_t mx;\n"
  401. "#ifdef RAM\n"
  402. " const char* buffer;\n"
  403. "#endif\n"
  404. "} mmu_t;\n"
  405. "#define DRAM_SIZE (1ULL << 32)\n"
  406. "#define SCRATCHPAD_SIZE (256 * 1024)\n"
  407. "#define SCRATCHPAD_LENGTH (SCRATCHPAD_SIZE / sizeof(convertible_t))\n"
  408. "#define SCRATCHPAD_MASK14 (16 * 1024 / sizeof(convertible_t) - 1)\n"
  409. "#define SCRATCHPAD_MASK18 (SCRATCHPAD_LENGTH - 1)\n"
  410. "#define SCRATCHPAD_16K(x) scratchpad[(x) & SCRATCHPAD_MASK14]\n"
  411. "#define SCRATCHPAD_256K(x) scratchpad[(x) & SCRATCHPAD_MASK18]\n"
  412. "#define STACK_LENGTH (128 * 1024)\n"
  413. "#ifdef RAM\n"
  414. "#define DRAM_READ(mmu) (convertible_t)*(uint64_t*)((mmu)->buffer + (mmu)->ma)\n"
  415. "#define PREFETCH(mmu) _mm_prefetch(((mmu)->buffer + (mmu)->ma), _MM_HINT_T0)\n"
  416. "#else\n"
  417. "#define DRAM_READ(mmu) (convertible_t)(uint64_t)__rolq(6364136223846793005ULL*((mmu)->ma)+1442695040888963407ULL,32)\n"
  418. "#define PREFETCH(mmu)\n"
  419. "#endif\n"
  420. "#define PUSH_VALUE(x) stack[sp++].value = x\n"
  421. "#define PUSH_ADDRESS(x) stack[sp++].address = x\n"
  422. "#define STACK_IS_EMPTY() (sp == 0)\n"
  423. "#define POP_VALUE() stack[--sp].value\n"
  424. "#define POP_ADDRESS() stack[--sp].address\n"
  425. "static convertible_t readDram(mmu_t* mmu, addr_t addr) {\n"
  426. " convertible_t data;\n"
  427. " data = DRAM_READ(mmu);\n"
  428. " mmu->ma += 8;\n"
  429. " mmu->mx ^= addr;\n"
  430. " if((mmu->mx & 0x1FFF) == 0) {\n"
  431. "#ifdef PRNTADDR\n"
  432. ' printf("DRAM jump %#010x -> %#010x\\n", mmu->ma, mmu->mx);\n'
  433. "#endif\n"
  434. " mmu->ma = mmu->mx;\n"
  435. "#ifdef PREF\n"
  436. " PREFETCH(mmu);\n"
  437. "#endif\n"
  438. " }\n"
  439. " return data;\n"
  440. "}\n"
  441. "static inline __m128i sl_xor(__m128i tmp1) {\n"
  442. " __m128i tmp4;\n"
  443. " tmp4 = _mm_slli_si128(tmp1, 0x04);\n"
  444. " tmp1 = _mm_xor_si128(tmp1, tmp4);\n"
  445. " tmp4 = _mm_slli_si128(tmp4, 0x04);\n"
  446. " tmp1 = _mm_xor_si128(tmp1, tmp4);\n"
  447. " tmp4 = _mm_slli_si128(tmp4, 0x04);\n"
  448. " tmp1 = _mm_xor_si128(tmp1, tmp4);\n"
  449. " return tmp1;\n"
  450. "}\n"
  451. "#define AES_GENKEY_SUB(rcon) do { \\\n"
  452. " __m128i xout1 = _mm_aeskeygenassist_si128(xout2, rcon); \\\n"
  453. " xout1 = _mm_shuffle_epi32(xout1, 0xFF); \\\n"
  454. " xout0 = sl_xor(xout0); \\\n"
  455. " xout0 = _mm_xor_si128(xout0, xout1); \\\n"
  456. " xout1 = _mm_aeskeygenassist_si128(xout0, 0x00); \\\n"
  457. " xout1 = _mm_shuffle_epi32(xout1, 0xAA); \\\n"
  458. " xout2 = sl_xor(xout2); \\\n"
  459. " xout2 = _mm_xor_si128(xout2, xout1); } while(0)\n"
  460. "static inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3, __m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9) {\n"
  461. " __m128i xout0, xout2;\n"
  462. " xout0 = _mm_load_si128(memory);\n"
  463. " xout2 = _mm_load_si128(memory+1);\n"
  464. " *k0 = xout0;\n"
  465. " *k1 = xout2;\n"
  466. " AES_GENKEY_SUB(0x01);\n"
  467. " *k2 = xout0;\n"
  468. " *k3 = xout2;\n"
  469. " AES_GENKEY_SUB(0x02);\n"
  470. " *k4 = xout0;\n"
  471. " *k5 = xout2;\n"
  472. " AES_GENKEY_SUB(0x04);\n"
  473. " *k6 = xout0;\n"
  474. " *k7 = xout2;\n"
  475. " AES_GENKEY_SUB(0x08);\n"
  476. " *k8 = xout0;\n"
  477. " *k9 = xout2;\n"
  478. "}\n"
  479. "static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7) {\n"
  480. " *x0 = _mm_aesenc_si128(*x0, key);\n"
  481. " *x1 = _mm_aesenc_si128(*x1, key);\n"
  482. " *x2 = _mm_aesenc_si128(*x2, key);\n"
  483. " *x3 = _mm_aesenc_si128(*x3, key);\n"
  484. " *x4 = _mm_aesenc_si128(*x4, key);\n"
  485. " *x5 = _mm_aesenc_si128(*x5, key);\n"
  486. " *x6 = _mm_aesenc_si128(*x6, key);\n"
  487. " *x7 = _mm_aesenc_si128(*x7, key);\n"
  488. "}\n"
  489. "static void aesInitialize(__m128i* key, __m128i* seed, __m128i* output, size_t count) {\n"
  490. " \n"
  491. " __m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7;\n"
  492. " __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;\n"
  493. " \n"
  494. " aes_genkey(key, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);\n"
  495. " \n"
  496. " xin0 = _mm_load_si128(seed + 0);\n"
  497. " xin1 = _mm_load_si128(seed + 1);\n"
  498. " xin2 = _mm_load_si128(seed + 2);\n"
  499. " xin3 = _mm_load_si128(seed + 3);\n"
  500. " xin4 = _mm_load_si128(seed + 4);\n"
  501. " xin5 = _mm_load_si128(seed + 5);\n"
  502. " xin6 = _mm_load_si128(seed + 6);\n"
  503. " xin7 = _mm_load_si128(seed + 7);\n"
  504. " \n"
  505. " for (size_t i = 0; i < count / sizeof(__m128i); i += 8)\n"
  506. " {\n"
  507. " aes_round(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);\n"
  508. " aes_round(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);\n"
  509. " aes_round(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);\n"
  510. " aes_round(k3, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);\n"
  511. " aes_round(k4, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);\n"
  512. " aes_round(k5, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);\n"
  513. " aes_round(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);\n"
  514. " aes_round(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);\n"
  515. " aes_round(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);\n"
  516. " aes_round(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);\n"
  517. " \n"
  518. " _mm_store_si128(output + i + 0, xin0);\n"
  519. " _mm_store_si128(output + i + 1, xin1);\n"
  520. " _mm_store_si128(output + i + 2, xin2);\n"
  521. " _mm_store_si128(output + i + 3, xin3);\n"
  522. " _mm_store_si128(output + i + 4, xin4);\n"
  523. " _mm_store_si128(output + i + 5, xin5);\n"
  524. " _mm_store_si128(output + i + 6, xin6);\n"
  525. " _mm_store_si128(output + i + 7, xin7);\n"
  526. " }\n"
  527. "}\n"))
  528. with sys.stdout as file:
  529. buildOpcodeMap()
  530. writeProlog(file)
  531. file.write("const byte aesKey[32] = {{ {0} }};\n".format(genBytes(32)))
  532. file.write("const byte aesSeed[128] = {{ {0} }};\n".format(genBytes(128)))
  533. writeMain(file)
  534. writeInitialValues(file)
  535. for i in range(PROGRAM_SIZE):
  536. writeCode(file, i, CodeSymbol(random.getrandbits(128)))
  537. if PROGRAM_SIZE > 0:
  538. file.write("\t\tgoto i_0;\n")
  539. writeEpilog(file)