Assembly.h 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363
  1. #pragma once
  2. #include <vector>
  3. #include "Array.h"
  4. #include "Text.h"
  5. #include "Writer.h"
  6. namespace Framework
  7. {
  8. namespace Assembly
  9. {
  10. enum Operation
  11. {
  12. // no real operation, used for labels
  13. NOP,
  14. // Arithmetic Operations
  15. ADD, // Addition
  16. ADDPD, // Add Packed Double-Precision Floating-Point Values
  17. ADDPS, // Add Packed Single-Precision Floating-Point Values
  18. ADDSD, // Add Scalar Double-Precision Floating-Point Values
  19. ADDSS, // Add Scalar Single-Precision Floating-Point Values
  20. SUB, // Subtraction
  21. SUBPD, // Subtract Packed Double-Precision Floating-Point Values
  22. SUBPS, // Subtract Packed Single-Precision Floating-Point Values
  23. SUBSD, // Subtract Scalar Double-Precision Floating-Point Values
  24. SUBSS, // Subtract Scalar Single-Precision Floating-Point Values
  25. MUL, // Multiply unsigned
  26. IMUL, // Multiply signed
  27. MULPD, // Multiply Packed Double Precision Floating-Point Values
  28. MULPS, // Multiply Packed Single Precision Floating-Point Values
  29. MULSD, // Multiply Scalar Double Precision Floating-Point Value
  30. MULSS, // Multiply Scalar Single Precision Floating-Point Values
  31. DIV, // Division unsigned
  32. IDIV, // Division signed
  33. DIVPD, // Divide Packed Double-Precision Floating-Point Values
  34. DIVPS, // Divide Packed Single-Precision Floating-Point Values
  35. DIVSD, // Divide Scalar Double-Precision Floating-Point Values
  36. DIVSS, // Divide Scalar Single-Precision Floating-Point Values
  37. NEG, // Negation
  38. INC, // Increment
  39. // Logical Operations
  40. AND, // Bitwise AND
  41. OR, // Bitwise OR
  42. XOR, // Bitwise XOR
  43. NOT, // Bitwise NOT
  44. // Comparison Operations
  45. // Bitwise AND without storing the result. only
  46. // SpecialRegister.FLAGS (SF, ZF, PF) is affected
  47. TEST,
  48. // Compare
  49. // temporary subtracts op2 from op without storing the result. only
  50. // SpecialRegister.FLAGS is affected
  51. CMP,
  52. // Compare Packed Double Precision Floating-Point Values
  53. CMPPD,
  54. // Compare Packed Single Precision Floating-Point Values
  55. CMPPS,
  56. // Compare Scalar Double Precision Floating-Point Value
  57. CMPSD,
  58. // Compare Scalar Single Precision Floating-Point Value
  59. CMPSS,
  60. // Compare Scalar Ordered Double Precision Floating-Point Values
  61. // writes to SpecialRegister.FLAGS (ZF, PF, CF)
  62. // UNORDERED (one of the values was NAN) = 0b111
  63. // GREATER_THAN = 0b000
  64. // LESS_THAN = 0b001
  65. // EQUAL = 0b100
  66. COMISD,
  67. // Compare Scalar Ordered Single Precision Floating-Point Values
  68. // writes to SpecialRegister.FLAGS (ZF, PF, CF)
  69. // UNORDERED (one of the values was NAN) = 0b111
  70. // GREATER_THAN = 0b000
  71. // LESS_THAN = 0b001
  72. // EQUAL = 0b100
  73. COMISS,
  74. // Data Movement
  75. MOV, // Move data from source to destination
  76. // Move Unaligned Packed Double-Precision Floating-Point Value
  77. MOVUPD,
  78. // Move Unaligned Packed Single-Precision Floating-Point Value
  79. MOVUPS,
  80. MOVSD, // Move Scalar Double-Precision Floating-Point Value
  81. MOVSS, // Move Scalar Single-Precision Floating-Point Value
  82. LEA, // Load Effective Address
  83. // DATA Conversion
  84. // Convert Integer to Scalar Double Precision Floating-Point Value
  85. CVTSI2SD,
  86. // Convert Integer to Scalar Single Precision Floating-Point Value
  87. CVTSI2SS,
  88. // Convert With Truncation Scalar Double Precision Floating-Point
  89. // Value to Signed Integer
  90. CVTTSD2SI,
  91. // Convert With Truncation Scalar Single Precision Floating-Point
  92. // Value to Signed Integer
  93. CVTTSS2SI,
  94. // Convert Scalar Double Precision Floating-Point Value to Integer
  95. // with rounding according to the bits 13 an 14 of the MXCSR
  96. // register value:
  97. //
  98. // 0b00: (default) round to nearest integer value
  99. // 0b01: round to the next lower integer value
  100. // 0b10: round to the next heigher integer value
  101. // 0b11: truncate (like CVTTSS2SI)
  102. CVTSD2SI,
  103. // Convert Scalar Single Precision Floating-Point Value to Integer
  104. // with rounding according to the bits 13 an 14 of the MXCSR
  105. // register value:
  106. //
  107. // 0b00: (default) round to nearest integer value
  108. // 0b01: round to the next lower integer value
  109. // 0b10: round to the next heigher integer value
  110. // 0b11: truncate (like CVTTSS2SI)
  111. CVTSS2SI,
  112. // Control Flow
  113. // Unconditional Jump
  114. JMP,
  115. // Jump if Zero: SpecialRegister.FLAGS(ZF) = 1
  116. JZ,
  117. // Jump if equal: SpecialRegister.FLAGS(ZF) = 1
  118. JE = JZ,
  119. // Jump if Not Zero: SpecialRegister.FLAGS(ZF) = 0
  120. JNZ,
  121. // Jump if Not Equal: SpecialRegister.FLAGS(ZF) = 0
  122. JNE = JNZ,
  123. // Jump if Greater: SpecialRegister.FLAGS(SF) =
  124. // SpecialRegister.FLAGS(OF) and SpecialRegister.FLAGS(ZF) = 0
  125. JG,
  126. // Jump if Greater or Equal: SpecialRegister.FLAGS(SF) =
  127. // SpecialRegister.FLAGS(OF)
  128. JGE,
  129. // Jump if Less: SpecialRegister.FLAGS(SF) !=
  130. // SpecialRegister.FLAGS(OF)
  131. JL,
  132. // Jump if Less or Equal: SpecialRegister.FLAGS(SF) !=
  133. // SpecialRegister.FLAGS(OF) or SpecialRegister.FLAGS(ZF) = 1
  134. JLE,
  135. // Jump if above: SpecialRegister.FLAGS(CF) = 0 and
  136. // SpecialRegister.FLAGS(ZF) = 0
  137. JA,
  138. // Jump if carry: SpecialRegister.FLAGS(CF) = 1
  139. JC,
  140. // Jump if below: SpecialRegister.FLAGS(CF) = 1
  141. JB = JC,
  142. // Jump if not carry: SpecialRegister.FLAGS(CF) = 0
  143. JNC,
  144. // Jump if not below: SpecialRegister.FLAGS(CF) = 0
  145. JNB = JNC,
  146. // Jump if below or equal: SpecialRegister.FLAGS(CF) = 1 or
  147. // SpecialRegister.FLAGS(ZF) = 1
  148. JBE,
  149. JO, // Jump if overflow: SpecialRegister.FLAGS(OF) = 1
  150. JNO, // Jump if not overflow: SpecialRegister.FLAGS(OF) = 0
  151. JP, // Jump if parity even: SpecialRegister.FLAGS(PF) = 1
  152. JNP, // Jump if not parity odd: SpecialRegister.FLAGS(PF) = 0
  153. JS, // Jump if sign: SpecialRegister.FLAGS(SF) = 1
  154. JNS, // Jump if not sign: SpecialRegister.FLAGS(SF) = 0
  155. CALL, // Call subroutine
  156. RET, // Return from subroutine
  157. // Stack Operations
  158. PUSH, // Push onto stack
  159. POP // Pop from stack
  160. };
  161. enum CMP_IMM8
  162. {
  163. EQ_OQ = 0, // Equal (ordered, non-signaling)
  164. LT_OS = 1, // Less than (ordered, signaling)
  165. LE_OS = 2, // Less than or equal (ordered, signaling
  166. UNORD_Q = 3, // Unordered (non-signaling)
  167. NEQ_UQ = 4, // Not-equal (unordered, non-signaling)
  168. NLT_US = 5, // Not less than (unordered, signaling)
  169. NLE_US = 6, // Not-less-than-or-equal (unordered, signaling)
  170. ORD_Q = 7, // Ordered (non-signaling)
  171. EQ_US = 8, // Equal (unordered, signaling)
  172. NGE_US = 9, // Not-greater-than-or-equal (unordered, signaling)
  173. NGT_US = 10, // Not-greater-than (unordered, signaling)
  174. FALSE_OQ = 11, // False (ordered, non-signaling)
  175. NEQ_OQ = 12, // Not-equal (ordered, non-signaling)
  176. GE_OS = 13, // Greater-than-or-equal (ordered, signaling)
  177. GT_OS = 14, // Greater-than (ordered, signaling)
  178. TRUE_UQ = 15, // True (unordered, non-signaling)
  179. EQ_OS = 16, // Equal (ordered, signaling)
  180. LT_OQ = 17, // Less-than (ordered, non-signaling)
  181. LE_OQ = 18, // Less-than-or-equal (ordered, non
  182. UNORD_S = 19, // Unordered (signaling)
  183. NEQ_US = 20, // Not-equal (unordered, signaling)
  184. NLT_UQ = 21, // Not-less-than (unordered, non-sign
  185. NLE_UQ = 22, // Not-less-than-or-equal (unordered, non-signaling)
  186. ORD_S = 23, // Ordered (signaling)
  187. EQ_UQ = 24, // Equal (unordered, non-signaling)
  188. NGE_UQ = 25, // Not-greater-than-or-equal (
  189. NGT_UQ = 26, // Not-greater-than (unordered, non-signaling)
  190. FALSE_OS = 27, // False (ordered, signaling)
  191. NEQ_OS = 28, // Not-equal (ordered, signaling)
  192. GE_OQ = 29, // Greater-than-or-equal (ordered, non
  193. GT_OQ = 30, // Greater-than (ordered, non-signaling)
  194. TRUE_S = 31 // True (signaling)
  195. };
  196. enum FPDataType
  197. {
  198. SINGLE_FLOAT,
  199. SINGLE_DOUBLE,
  200. PACKED_FLOAT,
  201. PACKED_DOUBLE
  202. };
  203. enum FuncReturnType
  204. {
  205. NO_VALUE,
  206. INT_VALUE,
  207. FLOAT_VALUE
  208. };
  209. // General Purpose Registers
  210. enum GPRegister
  211. {
  212. // volatile register (can be altered by a function call)
  213. RAX = 0b0000,
  214. // non-volatile register (mus be restored on return)
  215. RBX = 0b0011,
  216. // volatile register (can be altered by a function call)
  217. RCX = 0b0001,
  218. // volatile register (can be altered by a function call)
  219. RDX = 0b0010,
  220. // Stack pointer points to the position of the last item that was
  221. // pushed to the stack. The stack grows downwards so lower means
  222. // more elements in the stack. needs to be aligned to 16 bytes
  223. // non-volatile register (mus be restored on return)
  224. RSP = 0b0100,
  225. // base pointer points to the base of the current stack frame
  226. // non-volatile register (mus be restored on return)
  227. RBP = 0b0101,
  228. // non-volatile register (mus be restored on return)
  229. RSI = 0b0110,
  230. // non-volatile register (mus be restored on return)
  231. RDI = 0b0111,
  232. // volatile register (can be altered by a function call)
  233. R8 = 0b1000,
  234. // volatile register (can be altered by a function call)
  235. R9 = 0b1001,
  236. // volatile register (can be altered by a function call)
  237. R10 = 0b1010,
  238. // volatile register (can be altered by a function call)
  239. R11 = 0b1011,
  240. // non-volatile register (mus be restored on return)
  241. R12 = 0b1100,
  242. // non-volatile register (mus be restored on return)
  243. R13 = 0b1101,
  244. // non-volatile register (mus be restored on return)
  245. R14 = 0b1110,
  246. // non-volatile register (mus be restored on return)
  247. R15 = 0b1111
  248. };
  249. enum SpecialRegister
  250. {
  251. // Instruction pointer points to the instruction that is executed
  252. // next
  253. RIP,
  254. /**
  255. only lower 16 bits are used:
  256. - CF: Carry Flag
  257. - PF: Parity Flag (1 if an even number of bits was set to 1 in
  258. the result of the last operation)
  259. - AF: Adjust Flag
  260. - ZF: Zero Flag (1 if the result of the last operation was zero)
  261. - SF: Sign Flag (1 if the result of the last operation was a
  262. positive number)
  263. - TF: Trap Flag
  264. - IF: Interrupt Flag
  265. - DF: Direction Flag
  266. - OF: Overflow Flag
  267. */
  268. FLAGS,
  269. /**
  270. * controls the behaviour of some operations.
  271. */
  272. MXCSR,
  273. };
  274. /**
  275. floating point registers
  276. */
  277. enum FPRegister
  278. {
  279. MM0, // volatile register (can be altered by a function call)
  280. MM1, // volatile register (can be altered by a function call)
  281. MM2, // volatile register (can be altered by a function call)
  282. MM3, // volatile register (can be altered by a function call)
  283. MM4, // volatile register (can be altered by a function call)
  284. MM5, // volatile register (can be altered by a function call)
  285. MM6, // non volatile register (mus be restored on return)
  286. MM7, // non volatile register (mus be restored on return)
  287. MM8, // non volatile register (mus be restored on return)
  288. MM9, // non volatile register (mus be restored on return)
  289. MM10, // non volatile register (mus be restored on return)
  290. MM11, // non volatile register (mus be restored on return)
  291. MM12, // non volatile register (mus be restored on return)
  292. MM13, // non volatile register (mus be restored on return)
  293. MM14, // non volatile register (mus be restored on return)
  294. MM15, // non volatile register (mus be restored on return)
  295. __FP_REGISTER_COUNT
  296. };
  297. /**
  298. describes the bits of the specified register that should be used.
  299. */
  300. enum GPRegisterPart
  301. {
  302. LOWER8,
  303. HIGHER8,
  304. LOWER16,
  305. LOWER32,
  306. FULL64
  307. };
  308. /**
  309. describes the bits of the specified register that should be used.
  310. */
  311. enum FPRegisterPart
  312. {
  313. X,
  314. Y,
  315. // Z
  316. };
  317. class AssemblyBlock;
  318. class GPRegisterArgument;
  319. class FPRegisterArgument;
  320. class MemoryAccessArgument;
  321. class ConstantArgument;
  322. class JumpTargetArgument;
  323. /**
  324. An argument for an Instruction.
  325. */
  326. class OperationArgument
  327. {
  328. private:
  329. public:
  330. /**
  331. * checks if a register is used in this argument.
  332. *
  333. * \param reg the register to check
  334. * \return true if the register is used
  335. */
  336. DLLEXPORT virtual bool usesRegister(GPRegister reg) const;
  337. /**
  338. * checks if a register is used in this argument.
  339. *
  340. * \param reg the register to check
  341. * \return true if the register is used
  342. */
  343. DLLEXPORT virtual bool usesRegister(FPRegister reg) const;
  344. /**
  345. * replaces a register with another register.
  346. *
  347. * \param oldReg the register to replace
  348. * \param newReg the register to use instead
  349. */
  350. DLLEXPORT virtual void replaceRegister(
  351. GPRegister oldReg, GPRegister newReg);
  352. /**
  353. * replaces a register with another register.
  354. *
  355. * \param oldReg the register to replace
  356. * \param newReg the register to use instead
  357. */
  358. DLLEXPORT virtual void replaceRegister(
  359. FPRegister oldReg, FPRegister newReg);
  360. /**
  361. * adds a prefix to all jump labels in this argument to avoid
  362. * conflicts if the assembly block that contains this argument is
  363. * inlined into another block.
  364. *
  365. * \param labelPrefix the label prefix to add
  366. */
  367. DLLEXPORT virtual void addJumpLabelPrefix(Text labelPrefix);
  368. /**
  369. * \return the GPRegisterArgument or 0 if it is not a
  370. * GPRegisterArgument
  371. */
  372. DLLEXPORT const GPRegisterArgument* asGPRegisterArgument() const;
  373. /**
  374. * \return the GPRegisterArgument or 0 if it is not a
  375. * GPRegisterArgument
  376. */
  377. DLLEXPORT const MemoryAccessArgument*
  378. asMemoryAccessArgument() const;
  379. /**
  380. * \return the ConstantArgument or 0 if it is not a
  381. * ConstantArgument
  382. */
  383. DLLEXPORT const ConstantArgument* asConstantArgument() const;
  384. /**
  385. * \return the FPRegisterArgument or 0 if it is not a
  386. * FPRegisterArgument
  387. */
  388. DLLEXPORT const FPRegisterArgument* asFPRegisterArgument() const;
  389. /**
  390. * \return the JumpTargetArgument or 0 if it is not a
  391. * JumpTargetArgument
  392. */
  393. DLLEXPORT const JumpTargetArgument* asJumpTargetArgument() const;
  394. };
  395. /**
  396. Represents the usage of a GPRegister as an Instruction Argument.
  397. */
  398. class GPRegisterArgument : public OperationArgument
  399. {
  400. private:
  401. GPRegister reg;
  402. GPRegisterPart part;
  403. public:
  404. DLLEXPORT GPRegisterArgument(
  405. GPRegister reg, GPRegisterPart part = GPRegisterPart::FULL64);
  406. DLLEXPORT bool usesRegister(GPRegister reg) const override;
  407. DLLEXPORT void replaceRegister(
  408. GPRegister oldReg, GPRegister newReg) override;
  409. DLLEXPORT GPRegister getRegister() const;
  410. DLLEXPORT GPRegisterPart getPart() const;
  411. };
  412. /**
  413. Represents the usage of a FPRegister as an Instruction Argument.
  414. */
  415. class FPRegisterArgument : public OperationArgument
  416. {
  417. private:
  418. FPRegister reg;
  419. FPRegisterPart part;
  420. public:
  421. DLLEXPORT FPRegisterArgument(FPRegister reg, FPRegisterPart = X);
  422. DLLEXPORT bool usesRegister(FPRegister reg) const override;
  423. DLLEXPORT void replaceRegister(
  424. FPRegister oldReg, FPRegister newReg) override;
  425. DLLEXPORT FPRegister getRegister() const;
  426. DLLEXPORT FPRegisterPart getPart() const;
  427. };
  428. enum class MemoryBlockSize
  429. {
  430. // 8 bist
  431. BYTE = 1,
  432. // 16 bits
  433. WORD = 2,
  434. // 32 bits
  435. DWORD = 4,
  436. // 64 bits
  437. QWORD = 8,
  438. // 128 bits
  439. M128 = 16,
  440. // 256 bits
  441. M256 = 32,
  442. // 512 bits
  443. // M512 = 64
  444. };
  445. /**
  446. Represents the usage of a Memory Read Request as an Instruction
  447. Argument.
  448. */
  449. class MemoryAccessArgument : public OperationArgument
  450. {
  451. private:
  452. MemoryBlockSize blockSize; // size of the block to access (1,2,4,8)
  453. bool useAddressReg;
  454. GPRegister address;
  455. int offset; // offset from the address in the register
  456. GPRegister offsetReg;
  457. bool useOffsetReg;
  458. public:
  459. DLLEXPORT MemoryAccessArgument(MemoryBlockSize blockSize,
  460. GPRegister address,
  461. bool useAddressReg = true,
  462. int offset = 0,
  463. bool useOffsetReg = false,
  464. GPRegister offsetReg = RAX);
  465. DLLEXPORT bool usesRegister(GPRegister reg) const override;
  466. DLLEXPORT void replaceRegister(
  467. GPRegister oldReg, GPRegister newReg) override;
  468. DLLEXPORT bool isUsingAddressRegister() const;
  469. DLLEXPORT GPRegister getAddressRegister() const;
  470. DLLEXPORT int getOffset() const;
  471. DLLEXPORT bool isUsingOffsetRegister() const;
  472. DLLEXPORT GPRegister getOffsetRegister() const;
  473. DLLEXPORT MemoryBlockSize getBlockSize() const;
  474. };
  475. /**
  476. Represents the usage of a const value as an Instruction Argument.
  477. */
  478. class ConstantArgument : public OperationArgument
  479. {
  480. private:
  481. __int64 value;
  482. MemoryBlockSize size; // size in byte
  483. public:
  484. DLLEXPORT ConstantArgument(
  485. __int64 value, MemoryBlockSize size = MemoryBlockSize::QWORD);
  486. DLLEXPORT ConstantArgument(
  487. int value, MemoryBlockSize size = MemoryBlockSize::DWORD);
  488. DLLEXPORT ConstantArgument(
  489. short value, MemoryBlockSize size = MemoryBlockSize::WORD);
  490. DLLEXPORT ConstantArgument(
  491. char value, MemoryBlockSize size = MemoryBlockSize::BYTE);
  492. DLLEXPORT __int64 getValue() const;
  493. DLLEXPORT MemoryBlockSize getSize() const;
  494. };
  495. /**
  496. Represents the usage of a jump label as an Instruction Argument.
  497. */
  498. class JumpTargetArgument : public OperationArgument
  499. {
  500. private:
  501. Text name;
  502. public:
  503. DLLEXPORT JumpTargetArgument(Text name);
  504. DLLEXPORT void addJumpLabelPrefix(Text labelPrefix) override;
  505. const Text& getLabel() const;
  506. };
  507. /**
  508. Represents a single assembly instruction with its arguments.
  509. */
  510. class Instruction : public Framework::ReferenceCounter
  511. {
  512. private:
  513. Operation op;
  514. std::vector<OperationArgument*> args;
  515. std::vector<GPRegister> implicitReadGPs;
  516. std::vector<FPRegister> implicitReadFPs;
  517. std::vector<GPRegister> implicitWriteGPs;
  518. std::vector<FPRegister> implicitWriteFPs;
  519. public:
  520. DLLEXPORT Instruction(
  521. Operation op, std::initializer_list<OperationArgument*> params);
  522. DLLEXPORT Instruction(Operation op,
  523. std::initializer_list<OperationArgument*> params,
  524. std::initializer_list<GPRegister> implicitReadGPs,
  525. std::initializer_list<FPRegister> implicitReadFPs,
  526. std::initializer_list<GPRegister> implicitWriteGPs,
  527. std::initializer_list<FPRegister> implicitWriteFPs);
  528. DLLEXPORT ~Instruction();
  529. /**
  530. * checks if this instruction reads from a specified register.
  531. *
  532. * \param reg the register to check
  533. * \return true if the instruction reads from the register
  534. */
  535. DLLEXPORT bool writesToRegister(
  536. GPRegister reg, const AssemblyBlock* block) const;
  537. /**
  538. * checks if this instruction reads from a specified register.
  539. *
  540. * \param reg the register to check
  541. * \return true if the instruction reads from the register
  542. */
  543. DLLEXPORT bool writesToRegister(
  544. FPRegister reg, const AssemblyBlock* block) const;
  545. /**
  546. * checks if this instruction reads from a specified register.
  547. *
  548. * \param reg the register to check
  549. * \return true if the instruction reads from the register
  550. */
  551. DLLEXPORT bool readsFromRegister(
  552. GPRegister reg, const AssemblyBlock* block) const;
  553. /**
  554. * checks if this instruction reads from a specified register.
  555. *
  556. * \param reg the register to check
  557. * \return true if the instruction reads from the register
  558. */
  559. DLLEXPORT bool readsFromRegister(
  560. FPRegister reg, const AssemblyBlock* block) const;
  561. /**
  562. * checks if a register can be replaced by another register.
  563. *
  564. * \param oldReg the register to replace
  565. * \param newReg the register to use instead
  566. * \return true if the replacement is possible
  567. */
  568. DLLEXPORT bool isReplacementPossible(GPRegister oldReg,
  569. GPRegister newReg,
  570. const AssemblyBlock* block) const;
  571. /**
  572. * checks if a register can be replaced by another register.
  573. *
  574. * \param oldReg the register to replace
  575. * \param newReg the register to use instead
  576. * \return true if the replacement is possible
  577. */
  578. DLLEXPORT bool isReplacementPossible(FPRegister oldReg,
  579. FPRegister newReg,
  580. const AssemblyBlock* block) const;
  581. /**
  582. * replaces a register with another register.
  583. *
  584. * \param oldReg the register to replace
  585. * \param newReg the register to use instead
  586. */
  587. DLLEXPORT void replaceRegister(
  588. GPRegister oldReg, GPRegister newReg);
  589. /**
  590. * replaces a register with another register.
  591. *
  592. * \param oldReg the register to replace
  593. * \param newReg the register to use instead
  594. */
  595. DLLEXPORT void replaceRegister(
  596. FPRegister oldReg, FPRegister newReg);
  597. /**
  598. * adds a prefix to all jump labels in this instruction to avoid
  599. * conflicts if the assembly block that contains this instruction is
  600. * inlined into another block.
  601. *
  602. * \param labelPrefix the label prefix to add
  603. */
  604. DLLEXPORT void addJumpLabelPrefix(Text labelPrefix);
  605. /**
  606. * compiles this Instruction to macine code.
  607. *
  608. * \param machineCodeWriter the machine code will be written to this
  609. * writer
  610. * \param block the block that contains this instruction. needed to
  611. * resolve jump labels
  612. */
  613. DLLEXPORT void compile(StreamWriter* machineCodeWriter,
  614. const AssemblyBlock* block) const;
  615. /**
  616. * test if this instruction is valid.
  617. *
  618. * \param block the code block that contains this instruction
  619. * \return true if the instruction can be compiled
  620. */
  621. DLLEXPORT bool isValid(const AssemblyBlock* block) const;
  622. /**
  623. * calculates the bytes needed for this instruction in machine code.
  624. *
  625. * \return the bytes needed
  626. */
  627. DLLEXPORT int compiledSize(const AssemblyBlock* block) const;
  628. /**
  629. * \return the op code of this instruction
  630. */
  631. DLLEXPORT Operation getOperation() const;
  632. /**
  633. * \return true if the given label is defined by this operation
  634. */
  635. DLLEXPORT bool definesLabel(Text label) const;
  636. /**
  637. * \return the arguments of this instruction
  638. */
  639. DLLEXPORT const std::vector<OperationArgument*>&
  640. getArguments() const;
  641. };
  642. /**
  643. Represents a block of assembly instructions that can be compiled to
  644. machine code or inlined into another AssemblyBlock with addBlock(...).
  645. */
  646. class AssemblyBlock
  647. {
  648. private:
  649. RCArray<Instruction> instructions;
  650. int inlineIndex;
  651. void* compiledCode;
  652. public:
  653. DLLEXPORT AssemblyBlock();
  654. DLLEXPORT ~AssemblyBlock();
  655. /**
  656. * adds an instruction.
  657. *
  658. * \param instr the instruction to add.
  659. */
  660. DLLEXPORT void addInstruction(Instruction* instr);
  661. /**
  662. * defines a new jump target label.
  663. *
  664. * \param name the name of the label.
  665. */
  666. DLLEXPORT void defineJumpTarget(Text name);
  667. /**
  668. * adds a jump instruction that jumps to the next Instaruction after
  669. * the definition of the given label.
  670. *
  671. * \param jumpOp the op code of the jump iperation.
  672. * \param targetName the label to jump to.
  673. */
  674. DLLEXPORT void addJump(Operation jumpOp, Text targetName);
  675. /**
  676. * adds the value of the source register to the value of the target
  677. * register and stores the result in the target register. single
  678. * operation.
  679. *
  680. * \param target the target register
  681. * \param source the source register
  682. * \param part the register part
  683. */
  684. DLLEXPORT void addAddition(GPRegister target,
  685. GPRegister source,
  686. GPRegisterPart part = FULL64);
  687. /**
  688. * adds the given value to the given part of the target
  689. * register and stores the result in the given part of the target
  690. * register. single operation.
  691. *
  692. * \param target the target register
  693. * \param value the value to add
  694. * \param part the target register part
  695. */
  696. DLLEXPORT void addAddition(
  697. GPRegister target, char value, GPRegisterPart part = LOWER8);
  698. /**
  699. * adds the given value to the given part of the target
  700. * register and stores the result in the given part of the target
  701. * register. single operation.
  702. *
  703. * \param target the target register
  704. * \param value the value to add
  705. * \param part the target register part (only LOWER32 or FULL64 are
  706. * valid)
  707. */
  708. DLLEXPORT void addAddition(
  709. GPRegister target, int value, GPRegisterPart part = LOWER32);
  710. /**
  711. * adds the value of the source register to the value of the target
  712. * register and stores the result in the target register. single
  713. * operation.
  714. *
  715. * \param target the target register
  716. * \param source the source register
  717. * \param type the data type stored in the registers
  718. * \param part the register part
  719. */
  720. DLLEXPORT void addAddition(FPRegister target,
  721. FPRegister source,
  722. FPDataType type,
  723. FPRegisterPart part = Y);
  724. /**
  725. * subtracts the value of the source register from the value of the
  726. * target register and stores the result in the target register.
  727. * single operation.
  728. *
  729. * \param target the target register
  730. * \param source the source register
  731. * \param part the register part
  732. */
  733. DLLEXPORT void addSubtraction(GPRegister target,
  734. GPRegister source,
  735. GPRegisterPart part = FULL64);
  736. /**
  737. * subtracts the given value from the target register and stores the
  738. * result in the target register. single operation.
  739. *
  740. * \param target the target register
  741. * \param value the value to subtract
  742. * \param part the register part
  743. */
  744. DLLEXPORT void addSubtraction(
  745. GPRegister target, char value, GPRegisterPart part = LOWER8);
  746. /**
  747. * subtracts the given value from the target register and stores the
  748. * result in the target register. single operation.
  749. *
  750. * \param target the target register
  751. * \param value the value to subtract
  752. * \param part the register part
  753. */
  754. DLLEXPORT void addSubtraction(
  755. GPRegister target, int value, GPRegisterPart part = LOWER32);
  756. /**
  757. * subtracts the value of the target register from the value of the
  758. * source register and stores the result in the target register.
  759. * single operation.
  760. *
  761. * \param target the target register
  762. * \param source the source register
  763. * \param type the data type stored in the registers
  764. * \param part the register part
  765. */
  766. DLLEXPORT void addSubtraction(FPRegister target,
  767. FPRegister source,
  768. FPDataType type,
  769. FPRegisterPart part = Y);
  770. /**
  771. * multiplies the value of the source register to the value of the
  772. * target register and stores the result in the target register.
  773. * single operation.
  774. *
  775. * \param target the target register
  776. * \param source the source register
  777. * \param part the register part
  778. */
  779. DLLEXPORT void addMultiplication(GPRegister target,
  780. GPRegister source,
  781. GPRegisterPart part = FULL64);
  782. /**
  783. * multiplies the value of the source register to the value of the
  784. * target register and stores the result in the target register.
  785. * single operation.
  786. *
  787. * \param target the target register
  788. * \param source the source register
  789. * \param type the data type stored in the registers
  790. * \param part the register part
  791. */
  792. DLLEXPORT void addMultiplication(FPRegister target,
  793. FPRegister source,
  794. FPDataType type,
  795. FPRegisterPart part = Y);
  796. /**
  797. * devides the value of the target register by the value of the
  798. * source register and stores the result in the target register.
  799. * single operation.
  800. *
  801. * \param target the target register
  802. * \param source the source register
  803. * \param part the register part
  804. */
  805. DLLEXPORT void addDivision(GPRegister target,
  806. GPRegister source,
  807. GPRegisterPart part = FULL64);
  808. /**
  809. * devides the value of the target register by the value of the
  810. * source register and stores the result in the target register.
  811. * single operation.
  812. *
  813. * \param target the target register
  814. * \param source the source register
  815. * \param type the data type stored in the registers
  816. * \param part the register part
  817. */
  818. DLLEXPORT void addDivision(FPRegister target,
  819. FPRegister source,
  820. FPDataType type,
  821. FPRegisterPart part = Y);
  822. /**
  823. * performes bitwise AND without storing the result. only
  824. * SpecialRegister.FLAGS (SF, ZF, PF) is affected. Single operation.
  825. *
  826. * \param r1 the first value
  827. * \param r2 the second value
  828. * \param part the part of the values to test
  829. */
  830. DLLEXPORT void addTest(
  831. GPRegister r1, GPRegister r2, GPRegisterPart part = FULL64);
  832. /**
  833. * subtracts the value of r2 from r1 and sets FLAGS (CF, OF, SF, ZF,
  834. * AF, PF) according to the result. The result is discarded.
  835. *
  836. * \param r1 the first value
  837. * \param r2 the second value
  838. * \param part the part of the values to compare
  839. */
  840. DLLEXPORT void addCompare(
  841. GPRegister r1, GPRegister r2, GPRegisterPart part = FULL64);
  842. /**
  843. * subtracts the value from r1 and sets FLAGS (CF, OF, SF, ZF,
  844. * AF, PF) according to the result. The result is discarded.
  845. *
  846. * \param r1 the first value
  847. * \param value the value to subtract
  848. */
  849. DLLEXPORT void addCompare(GPRegister r1, char value);
  850. /**
  851. * subtracts the value from r1 and sets FLAGS (CF, OF, SF, ZF,
  852. * AF, PF) according to the result. The result is discarded.
  853. *
  854. * \param r1 the first value
  855. * \param value the value to subtract
  856. */
  857. DLLEXPORT void addCompare(GPRegister r1, short value);
  858. /**
  859. * subtracts the value from r1 and sets FLAGS (CF, OF, SF, ZF,
  860. * AF, PF) according to the result. The result is discarded.
  861. *
  862. * \param r1 the first value
  863. * \param value the value to subtract
  864. */
  865. DLLEXPORT void addCompare(GPRegister r1, int value);
  866. /**
  867. * subtracts the value of r2 from r1 and sets FLAGS (ZF, PF, CF).
  868. * the result is discarded
  869. *
  870. * UNORDERED: ZF,PF,CF := 111;
  871. * GREATER_THAN: ZF,PF,CF := 000;
  872. * LESS_THAN: ZF,PF,CF := 001;
  873. * EUAL: ZF,PF,CF := 100;
  874. *
  875. * \param r1 the first value
  876. * \param r2 the second value
  877. * \param type the datatype to compare. only SINGLE types are valid
  878. */
  879. DLLEXPORT void addCompare(
  880. FPRegister r1, FPRegister r2, FPDataType type);
  881. /**
  882. * computes bitwise AND for the values in source and target
  883. * register and stores the result in the target register. single
  884. * operation
  885. *
  886. * \param target the target register
  887. * \param source the source register
  888. * \param part the register part
  889. */
  890. DLLEXPORT void addAnd(GPRegister target,
  891. GPRegister source,
  892. GPRegisterPart part = FULL64);
  893. /**
  894. * computes bitwise AND for the values in source and target register
  895. * and stores the result in the target register. single operation
  896. *
  897. * \param target the target register
  898. * \param source the source register
  899. * \param part the register part
  900. */
  901. DLLEXPORT void addOr(GPRegister target,
  902. GPRegister source,
  903. GPRegisterPart part = FULL64);
  904. /**
  905. * writes the value at the specified valueAddress pointer into a
  906. * register.
  907. *
  908. * \param valueAddress the pointer to the value
  909. * \param target the register where the value should be stored
  910. */
  911. DLLEXPORT void addLoadValue(char* valueAddress, GPRegister target);
  912. /**
  913. * writes the value at the specified valueAddress pointer into a
  914. * register.
  915. *
  916. * \param valueAddress the pointer to the value
  917. * \param target the register where the value should be stored
  918. */
  919. DLLEXPORT void addLoadValue(short* valueAddress, GPRegister target);
  920. /**
  921. * writes the value at the specified valueAddress pointer into a
  922. * register.
  923. *
  924. * \param valueAddress the pointer to the value
  925. * \param target the register where the value should be stored
  926. */
  927. DLLEXPORT void addLoadValue(int* valueAddress, GPRegister target);
  928. /**
  929. * writes the value at the specified valueAddress pointer into a
  930. * register.
  931. *
  932. * \param valueAddress the pointer to the value
  933. * \param target the register where the value should be stored
  934. */
  935. DLLEXPORT void addLoadValue(
  936. __int64* valueAddress, GPRegister target);
  937. /**
  938. * loads the value at the address stored in addressRegister into the
  939. * target register. Single operation.
  940. *
  941. * \param addressRegister a register that contains a memory address
  942. * \param target the target register to store the value into
  943. * \param targetPart the part of the target register that will be
  944. * written to
  945. */
  946. DLLEXPORT void addLoadValue(GPRegister addressRegister,
  947. GPRegister target,
  948. GPRegisterPart targetPart,
  949. int offset = 0);
  950. /**
  951. * writes the specified valueAddress pointer into a register.
  952. *
  953. * \param valueAddress the pointer to the value witch address should
  954. * be stored
  955. * \param target the register where the address should be stored
  956. */
  957. DLLEXPORT void addLoadValue(
  958. float* valueAddress, FPRegister target, GPRegister temp = RAX);
  959. /**
  960. * writes the specified valueAddress pointer into a register.
  961. *
  962. * \param valueAddress the pointer to the value witch address should
  963. * be stored
  964. * \param target the register where the address should be stored
  965. */
  966. DLLEXPORT void addLoadValue(
  967. double* valueAddress, FPRegister target, GPRegister temp = RAX);
  968. /**
  969. * loads a memory address into a register. Single operation.
  970. *
  971. * \param addr the address to load
  972. * \param target the register where the address should be stored
  973. */
  974. template<typename T>
  975. DLLEXPORT void addLoadAddress(T* addr, GPRegister target = RAX)
  976. {
  977. instructions.add(new Instruction(MOV,
  978. {new GPRegisterArgument(target),
  979. new ConstantArgument(
  980. reinterpret_cast<__int64>(addr))}));
  981. }
  982. /**
  983. * moves the given value to LOWER8 bits of target register.
  984. *
  985. * \param target the register to move the value to
  986. * \param value the value to move
  987. */
  988. DLLEXPORT void addMoveValue(GPRegister target, char value);
  989. /**
  990. * moves the given value to LOWER16 bits of target register.
  991. *
  992. * \param target the register to move the value to
  993. * \param value the value to move
  994. */
  995. DLLEXPORT void addMoveValue(GPRegister target, short value);
  996. /**
  997. * moves the given value to LOWER32 bits of target register.
  998. *
  999. * \param target the register to move the value to
  1000. * \param value the value to move
  1001. */
  1002. DLLEXPORT void addMoveValue(GPRegister target, int value);
  1003. /**
  1004. * moves the given value to LOWER64 bits of target register.
  1005. *
  1006. * \param target the register to move the value to
  1007. * \param value the value to move
  1008. */
  1009. DLLEXPORT void addMoveValue(GPRegister target, __int64 value);
  1010. /**
  1011. * moves the given value to LOWER32 bits of target register.
  1012. * The value needs to be temporarily pushed to the stack, so
  1013. * addLoadValue should be used if performance is critical.
  1014. *
  1015. * \param target the register to move the value to
  1016. * \param value the value to move
  1017. * \param temp temporary register that can be used us store the
  1018. * value
  1019. */
  1020. DLLEXPORT void addMoveValue(
  1021. FPRegister target, float value, GPRegister temp = RAX);
  1022. /**
  1023. * moves the given value to LOWER64 bits of target register.
  1024. * The value needs to be temporarily pushed to the stack, so
  1025. * addLoadValue should be used if performance is critical.
  1026. *
  1027. * \param target the register to move the value to
  1028. * \param value the value to move
  1029. * \param temp temporary register that can be used us store the
  1030. * value
  1031. */
  1032. DLLEXPORT void addMoveValue(
  1033. FPRegister target, double value, GPRegister temp = RAX);
  1034. /**
  1035. * moves the value from source register to target register.
  1036. *
  1037. * \param target the register to move the value to
  1038. * \param source the register to move the value from
  1039. * \param part the part of the register to move
  1040. */
  1041. DLLEXPORT void addMoveValue(GPRegister target,
  1042. GPRegister source,
  1043. GPRegisterPart part = FULL64);
  1044. /**
  1045. * moves the value from source register to target register.
  1046. *
  1047. * \param target the register to move the value to
  1048. * \param source the register to move the value from
  1049. * \param part the part of the register to move
  1050. */
  1051. DLLEXPORT void addMoveValue(FPRegister target,
  1052. FPRegister source,
  1053. FPDataType type,
  1054. FPRegisterPart part = Y);
  1055. /**
  1056. * converts a floating point value from source register into a
  1057. * signed integer value and writes it into the target register.
  1058. * Single operation.
  1059. *
  1060. * \param target the target register
  1061. * \param source the source register
  1062. * \param type the datatype of the source register. Only SINGLE
  1063. * types are valid.
  1064. * \param targetPart the register part to write the result into.
  1065. * Only LOWER32 or FULL64 are valid.
  1066. * \param round if true the value is rounded acourding to bits 13
  1067. * and 14 of the MXCSR register value
  1068. */
  1069. DLLEXPORT void addConversion(GPRegister target,
  1070. FPRegister source,
  1071. FPDataType type,
  1072. GPRegisterPart targetPart,
  1073. bool round = 0);
  1074. /**
  1075. * converts a signed integer from source register into a floating
  1076. * point value and writes it into the target register. Single
  1077. * operation
  1078. *
  1079. * \param target the target register
  1080. * \param source the source register
  1081. * \param targetType the data type after the conversion. Only SINGLE
  1082. * types are valid.
  1083. * \param sourcePart the register part that contains the signed
  1084. * integer. Only LOWER32 and FULL64 are valid.
  1085. */
  1086. DLLEXPORT void addConversion(FPRegister target,
  1087. GPRegister source,
  1088. FPDataType targetType,
  1089. GPRegisterPart sourcePart);
  1090. /**
  1091. * calls a function at a specified memory address.
  1092. *
  1093. * \param functionAddress pointet to the address of the function to
  1094. * call
  1095. * \param gpParams must be the the every n-th entry of the register
  1096. * list (RCX, RDX, R8, R9) for each n-th function parameter that is
  1097. * of type integer
  1098. * \param fpParams must be the the every n-th entry of the register
  1099. * list (MM0, MM1, MM2, MM3) for each n-th function parameter that
  1100. * is of type float/double
  1101. * \param temp temporary register to store the address of the
  1102. * function
  1103. * \param bpTemp temporary register to store the stack pointer
  1104. * before ligning the stack pointer to a 16 byte boundry. The stack
  1105. * pointer will be automatically restored after the function call
  1106. * using the value of this register. A non-volatile register must be
  1107. * used.
  1108. */
  1109. DLLEXPORT void addCall(void* functionAddress,
  1110. FuncReturnType returnType = NO_VALUE,
  1111. std::initializer_list<GPRegister> gpParams = {},
  1112. std::initializer_list<FPRegister> fpParams = {},
  1113. GPRegister temp = RAX,
  1114. GPRegister bpTemp = RBP);
  1115. /**
  1116. * calls a function at a specified memory address.
  1117. *
  1118. * \param functionAddress pointet to the address of the function to
  1119. * call
  1120. * \param gpParams must be the the every n-th entry of the register
  1121. * list (RCX, RDX, R8, R9) for each n-th function parameter that is
  1122. * of type integer
  1123. * \param fpParams must be the the every n-th entry of the register
  1124. * list (MM0, MM1, MM2, MM3) for each n-th function parameter that
  1125. * is of type float/double
  1126. * \param temp temporary register to store the address of the
  1127. * function
  1128. * \param bpTemp temporary register to store the stack pointer
  1129. * before ligning the stack pointer to a 16 byte boundry. The stack
  1130. * pointer will be automatically restored after the function call
  1131. * using the value of this register. A non-volatile register must be
  1132. * used.
  1133. */
  1134. template<typename T>
  1135. DLLEXPORT void addMemberCall(T&& functionAddress,
  1136. FuncReturnType returnType = NO_VALUE,
  1137. std::initializer_list<GPRegister> gpParams = {},
  1138. std::initializer_list<FPRegister> fpParams = {},
  1139. GPRegister temp = RAX,
  1140. GPRegister bpTemp = RBP)
  1141. {
  1142. addCall((void*&)functionAddress,
  1143. returnType,
  1144. gpParams,
  1145. fpParams,
  1146. temp,
  1147. bpTemp);
  1148. }
  1149. /**
  1150. * returns from executing the compiled assembly function.
  1151. */
  1152. DLLEXPORT void addReturn();
  1153. /**
  1154. * pushes a register into the stack.
  1155. *
  1156. * \param reg the register to push
  1157. * \param part the part of the register to push
  1158. */
  1159. DLLEXPORT void addPush(
  1160. GPRegister reg, GPRegisterPart part = FULL64);
  1161. /**
  1162. * pops a value from the sack into a specified register.
  1163. *
  1164. * \param reg the register to store the popped value
  1165. * \param part the part of the register to store the popped value
  1166. */
  1167. DLLEXPORT void addPop(GPRegister reg, GPRegisterPart part = FULL64);
  1168. /**
  1169. * pushes a register into the stack.
  1170. *
  1171. * \param reg the register to push
  1172. * \param type the datatype of the register
  1173. * \param part the part of the register
  1174. */
  1175. DLLEXPORT void addPush(
  1176. FPRegister reg, FPDataType type, FPRegisterPart part = X);
  1177. /**
  1178. * pops a value from the sack into a specified register.
  1179. *
  1180. * \param reg the register to store the popped value
  1181. * \param type the datatype of the register
  1182. * \param part the part of the register
  1183. */
  1184. DLLEXPORT void addPop(
  1185. FPRegister reg, FPDataType type, FPRegisterPart part = X);
  1186. private:
  1187. DLLEXPORT void addPop(RCArray<Instruction>& instructionList,
  1188. FPRegister reg,
  1189. FPDataType type,
  1190. FPRegisterPart part = X);
  1191. public:
  1192. /**
  1193. * copies the assembly code from a given block of assembly
  1194. * instructions.
  1195. *
  1196. * \param block the block to inline
  1197. * \param preservedGPRegisters the GP registers that should be
  1198. * preserved during the inlined block. if a preserved register is
  1199. * used in the block, it will be replaced by another register or
  1200. * pushed to the stack if no free register is available.
  1201. * \param preservedFPRegisters same as preservedGPRegisters but for
  1202. * FP registers
  1203. * \param preservedFPDataTypes data types of the preserved FP
  1204. * registers used to push them to the stack if needed
  1205. * \param blockResultGpReg if the register this pointer points to
  1206. * should be preserved this pointer will be set to the register that
  1207. * was selected to replace the register during execution of the
  1208. * block. Ignored if 0.
  1209. * \param blockResultFpReg same as blockResultGpReg but for FP
  1210. * Registers
  1211. */
  1212. DLLEXPORT void addBlock(AssemblyBlock* block,
  1213. std::initializer_list<GPRegister> preservedGPRegisters,
  1214. std::initializer_list<FPRegister> preservedFPRegisters,
  1215. std::initializer_list<FPDataType> preservedFPDataTypes,
  1216. GPRegister* blockResultGpReg,
  1217. FPRegister* blockResultFpReg);
  1218. /**
  1219. * checks if this block writes to a specified register.
  1220. *
  1221. * \param reg the register to check
  1222. * \return true if the block writes to the register
  1223. */
  1224. DLLEXPORT bool writesToRegister(GPRegister reg) const;
  1225. /**
  1226. * checks if this block writes to a specified register.
  1227. *
  1228. * \param reg the register to check
  1229. * \return true if the block writes to the register
  1230. */
  1231. DLLEXPORT bool writesToRegister(FPRegister reg) const;
  1232. /**
  1233. * checks if this block reads from a specified register.
  1234. *
  1235. * \param reg the register to check
  1236. * \return true if the block reads from the register
  1237. */
  1238. DLLEXPORT bool readsFromRegister(GPRegister reg) const;
  1239. /**
  1240. * checks if this block reads from a specified register.
  1241. *
  1242. * \param reg the register to check
  1243. * \return true if the block reads from the register
  1244. */
  1245. DLLEXPORT bool readsFromRegister(FPRegister reg) const;
  1246. /**
  1247. * checks if a register can be replaced by another register.
  1248. *
  1249. * \param oldReg the register to replace
  1250. * \param newReg the register to use instead
  1251. * \return true if the replacement is possible
  1252. */
  1253. DLLEXPORT bool isReplacementPossible(
  1254. GPRegister oldReg, GPRegister newReg) const;
  1255. /**
  1256. * checks if a register can be replaced by another register.
  1257. *
  1258. * \param oldReg the register to replace
  1259. * \param newReg the register to use instead
  1260. * \return true if the replacement is possible
  1261. */
  1262. DLLEXPORT bool isReplacementPossible(
  1263. FPRegister oldReg, FPRegister newReg) const;
  1264. /**
  1265. * replaces a register with another register.
  1266. *
  1267. * \param oldReg the register to replace
  1268. * \param newReg the register to use instead
  1269. */
  1270. DLLEXPORT void replaceRegister(
  1271. GPRegister oldReg, GPRegister newReg);
  1272. /**
  1273. * replaces a register with another register.
  1274. *
  1275. * \param oldReg the register to replace
  1276. * \param newReg the register to use instead
  1277. */
  1278. DLLEXPORT void replaceRegister(
  1279. FPRegister oldReg, FPRegister newReg);
  1280. /**
  1281. * adds a prefix to all jump labels in this block to avoid conflicts
  1282. * if this block is inlined into another block.
  1283. *
  1284. * \param labelPrefix the label prefix to add
  1285. */
  1286. DLLEXPORT void addJumpLabelPrefix(Text labelPrefix);
  1287. /**
  1288. * \return the instructions of this block
  1289. */
  1290. DLLEXPORT const RCArray<Instruction>& getInstructions() const;
  1291. /**
  1292. * performs optimisations to shorten the needed instructions.
  1293. *
  1294. */
  1295. DLLEXPORT void optimize();
  1296. /**
  1297. * \return a pointer to a function that contains the compiled byte
  1298. * code of this assembly block. and can be called directly with
  1299. * reinterpret_cast<returnType(*)(parameterTypes...)>(compile())(parameters...)
  1300. */
  1301. DLLEXPORT void* compile();
  1302. /**
  1303. * \return a pointer to a function that contains the compiled byte
  1304. * code of this assembly block. and can be called directly with
  1305. */
  1306. template<typename T> DLLEXPORT T compileToFunction()
  1307. {
  1308. return reinterpret_cast<T>(compile());
  1309. }
  1310. };
  1311. } // namespace Assembly
  1312. } // namespace Framework