Assembly.h 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367
  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. DLLEXPORT virtual ~OperationArgument() = default;
  331. /**
  332. * checks if a register is used in this argument.
  333. *
  334. * \param reg the register to check
  335. * \return true if the register is used
  336. */
  337. DLLEXPORT virtual bool usesRegister(GPRegister reg) const;
  338. /**
  339. * checks if a register is used in this argument.
  340. *
  341. * \param reg the register to check
  342. * \return true if the register is used
  343. */
  344. DLLEXPORT virtual bool usesRegister(FPRegister reg) const;
  345. /**
  346. * replaces a register with another register.
  347. *
  348. * \param oldReg the register to replace
  349. * \param newReg the register to use instead
  350. */
  351. DLLEXPORT virtual void replaceRegister(
  352. GPRegister oldReg, GPRegister newReg);
  353. /**
  354. * replaces a register with another register.
  355. *
  356. * \param oldReg the register to replace
  357. * \param newReg the register to use instead
  358. */
  359. DLLEXPORT virtual void replaceRegister(
  360. FPRegister oldReg, FPRegister newReg);
  361. /**
  362. * adds a prefix to all jump labels in this argument to avoid
  363. * conflicts if the assembly block that contains this argument is
  364. * inlined into another block.
  365. *
  366. * \param labelPrefix the label prefix to add
  367. */
  368. DLLEXPORT virtual void addJumpLabelPrefix(Text labelPrefix);
  369. /**
  370. * \return the GPRegisterArgument or 0 if it is not a
  371. * GPRegisterArgument
  372. */
  373. DLLEXPORT const GPRegisterArgument* asGPRegisterArgument() const;
  374. /**
  375. * \return the GPRegisterArgument or 0 if it is not a
  376. * GPRegisterArgument
  377. */
  378. DLLEXPORT const MemoryAccessArgument*
  379. asMemoryAccessArgument() const;
  380. /**
  381. * \return the ConstantArgument or 0 if it is not a
  382. * ConstantArgument
  383. */
  384. DLLEXPORT const ConstantArgument* asConstantArgument() const;
  385. /**
  386. * \return the FPRegisterArgument or 0 if it is not a
  387. * FPRegisterArgument
  388. */
  389. DLLEXPORT const FPRegisterArgument* asFPRegisterArgument() const;
  390. /**
  391. * \return the JumpTargetArgument or 0 if it is not a
  392. * JumpTargetArgument
  393. */
  394. DLLEXPORT const JumpTargetArgument* asJumpTargetArgument() const;
  395. };
  396. /**
  397. Represents the usage of a GPRegister as an Instruction Argument.
  398. */
  399. class GPRegisterArgument : public OperationArgument
  400. {
  401. private:
  402. GPRegister reg;
  403. GPRegisterPart part;
  404. public:
  405. DLLEXPORT GPRegisterArgument(
  406. GPRegister reg, GPRegisterPart part = GPRegisterPart::FULL64);
  407. DLLEXPORT bool usesRegister(GPRegister reg) const override;
  408. DLLEXPORT void replaceRegister(
  409. GPRegister oldReg, GPRegister newReg) override;
  410. DLLEXPORT GPRegister getRegister() const;
  411. DLLEXPORT GPRegisterPart getPart() const;
  412. };
  413. /**
  414. Represents the usage of a FPRegister as an Instruction Argument.
  415. */
  416. class FPRegisterArgument : public OperationArgument
  417. {
  418. private:
  419. FPRegister reg;
  420. FPRegisterPart part;
  421. public:
  422. DLLEXPORT FPRegisterArgument(FPRegister reg, FPRegisterPart = X);
  423. DLLEXPORT bool usesRegister(FPRegister reg) const override;
  424. DLLEXPORT void replaceRegister(
  425. FPRegister oldReg, FPRegister newReg) override;
  426. DLLEXPORT FPRegister getRegister() const;
  427. DLLEXPORT FPRegisterPart getPart() const;
  428. };
  429. enum class MemoryBlockSize
  430. {
  431. // 8 bist
  432. BYTE = 1,
  433. // 16 bits
  434. WORD = 2,
  435. // 32 bits
  436. DWORD = 4,
  437. // 64 bits
  438. QWORD = 8,
  439. // 128 bits
  440. M128 = 16,
  441. // 256 bits
  442. M256 = 32,
  443. // 512 bits
  444. // M512 = 64
  445. };
  446. /**
  447. Represents the usage of a Memory Read Request as an Instruction
  448. Argument.
  449. */
  450. class MemoryAccessArgument : public OperationArgument
  451. {
  452. private:
  453. MemoryBlockSize blockSize; // size of the block to access (1,2,4,8)
  454. bool useAddressReg;
  455. GPRegister address;
  456. int offset; // offset from the address in the register
  457. GPRegister offsetReg;
  458. bool useOffsetReg;
  459. public:
  460. DLLEXPORT MemoryAccessArgument(MemoryBlockSize blockSize,
  461. GPRegister address,
  462. bool useAddressReg = true,
  463. int offset = 0,
  464. bool useOffsetReg = false,
  465. GPRegister offsetReg = RAX);
  466. DLLEXPORT bool usesRegister(GPRegister reg) const override;
  467. DLLEXPORT void replaceRegister(
  468. GPRegister oldReg, GPRegister newReg) override;
  469. DLLEXPORT bool isUsingAddressRegister() const;
  470. DLLEXPORT GPRegister getAddressRegister() const;
  471. DLLEXPORT int getOffset() const;
  472. DLLEXPORT bool isUsingOffsetRegister() const;
  473. DLLEXPORT GPRegister getOffsetRegister() const;
  474. DLLEXPORT MemoryBlockSize getBlockSize() const;
  475. };
  476. /**
  477. Represents the usage of a const value as an Instruction Argument.
  478. */
  479. class ConstantArgument : public OperationArgument
  480. {
  481. private:
  482. __int64 value;
  483. MemoryBlockSize size; // size in byte
  484. public:
  485. DLLEXPORT ConstantArgument(
  486. __int64 value, MemoryBlockSize size = MemoryBlockSize::QWORD);
  487. DLLEXPORT ConstantArgument(
  488. int value, MemoryBlockSize size = MemoryBlockSize::DWORD);
  489. DLLEXPORT ConstantArgument(
  490. short value, MemoryBlockSize size = MemoryBlockSize::WORD);
  491. DLLEXPORT ConstantArgument(
  492. char value, MemoryBlockSize size = MemoryBlockSize::BYTE);
  493. DLLEXPORT __int64 getValue() const;
  494. DLLEXPORT MemoryBlockSize getSize() const;
  495. };
  496. /**
  497. Represents the usage of a jump label as an Instruction Argument.
  498. */
  499. class JumpTargetArgument : public OperationArgument
  500. {
  501. private:
  502. Text name;
  503. public:
  504. DLLEXPORT JumpTargetArgument(Text name);
  505. DLLEXPORT void addJumpLabelPrefix(Text labelPrefix) override;
  506. const Text& getLabel() const;
  507. };
  508. /**
  509. Represents a single assembly instruction with its arguments.
  510. */
  511. class Instruction : public Framework::ReferenceCounter
  512. {
  513. private:
  514. Operation op;
  515. std::vector<OperationArgument*> args;
  516. std::vector<GPRegister> implicitReadGPs;
  517. std::vector<FPRegister> implicitReadFPs;
  518. std::vector<GPRegister> implicitWriteGPs;
  519. std::vector<FPRegister> implicitWriteFPs;
  520. public:
  521. DLLEXPORT Instruction(
  522. Operation op, std::initializer_list<OperationArgument*> params);
  523. DLLEXPORT Instruction(Operation op,
  524. std::initializer_list<OperationArgument*> params,
  525. std::initializer_list<GPRegister> implicitReadGPs,
  526. std::initializer_list<FPRegister> implicitReadFPs,
  527. std::initializer_list<GPRegister> implicitWriteGPs,
  528. std::initializer_list<FPRegister> implicitWriteFPs);
  529. DLLEXPORT ~Instruction();
  530. /**
  531. * checks if this instruction reads from a specified register.
  532. *
  533. * \param reg the register to check
  534. * \return true if the instruction reads from the register
  535. */
  536. DLLEXPORT bool writesToRegister(
  537. GPRegister reg, const AssemblyBlock* block) const;
  538. /**
  539. * checks if this instruction reads from a specified register.
  540. *
  541. * \param reg the register to check
  542. * \return true if the instruction reads from the register
  543. */
  544. DLLEXPORT bool writesToRegister(
  545. FPRegister reg, const AssemblyBlock* block) const;
  546. /**
  547. * checks if this instruction reads from a specified register.
  548. *
  549. * \param reg the register to check
  550. * \return true if the instruction reads from the register
  551. */
  552. DLLEXPORT bool readsFromRegister(
  553. GPRegister reg, const AssemblyBlock* block) const;
  554. /**
  555. * checks if this instruction reads from a specified register.
  556. *
  557. * \param reg the register to check
  558. * \return true if the instruction reads from the register
  559. */
  560. DLLEXPORT bool readsFromRegister(
  561. FPRegister reg, const AssemblyBlock* block) const;
  562. /**
  563. * checks if a register can be replaced by another register.
  564. *
  565. * \param oldReg the register to replace
  566. * \param newReg the register to use instead
  567. * \return true if the replacement is possible
  568. */
  569. DLLEXPORT bool isReplacementPossible(GPRegister oldReg,
  570. GPRegister newReg,
  571. const AssemblyBlock* block) const;
  572. /**
  573. * checks if a register can be replaced by another register.
  574. *
  575. * \param oldReg the register to replace
  576. * \param newReg the register to use instead
  577. * \return true if the replacement is possible
  578. */
  579. DLLEXPORT bool isReplacementPossible(FPRegister oldReg,
  580. FPRegister newReg,
  581. const AssemblyBlock* block) const;
  582. /**
  583. * replaces a register with another register.
  584. *
  585. * \param oldReg the register to replace
  586. * \param newReg the register to use instead
  587. */
  588. DLLEXPORT void replaceRegister(
  589. GPRegister oldReg, GPRegister newReg);
  590. /**
  591. * replaces a register with another register.
  592. *
  593. * \param oldReg the register to replace
  594. * \param newReg the register to use instead
  595. */
  596. DLLEXPORT void replaceRegister(
  597. FPRegister oldReg, FPRegister newReg);
  598. /**
  599. * adds a prefix to all jump labels in this instruction to avoid
  600. * conflicts if the assembly block that contains this instruction is
  601. * inlined into another block.
  602. *
  603. * \param labelPrefix the label prefix to add
  604. */
  605. DLLEXPORT void addJumpLabelPrefix(Text labelPrefix);
  606. /**
  607. * compiles this Instruction to macine code.
  608. *
  609. * \param machineCodeWriter the machine code will be written to this
  610. * writer
  611. * \param block the block that contains this instruction. needed to
  612. * resolve jump labels
  613. */
  614. DLLEXPORT void compile(StreamWriter* machineCodeWriter,
  615. const AssemblyBlock* block) const;
  616. /**
  617. * test if this instruction is valid.
  618. *
  619. * \param block the code block that contains this instruction
  620. * \return true if the instruction can be compiled
  621. */
  622. DLLEXPORT bool isValid(const AssemblyBlock* block) const;
  623. /**
  624. * calculates the bytes needed for this instruction in machine code.
  625. *
  626. * \return the bytes needed
  627. */
  628. DLLEXPORT int compiledSize(const AssemblyBlock* block) const;
  629. /**
  630. * \return the op code of this instruction
  631. */
  632. DLLEXPORT Operation getOperation() const;
  633. /**
  634. * \return true if the given label is defined by this operation
  635. */
  636. DLLEXPORT bool definesLabel(Text label) const;
  637. /**
  638. * \return the arguments of this instruction
  639. */
  640. DLLEXPORT const std::vector<OperationArgument*>&
  641. getArguments() const;
  642. };
  643. /**
  644. Represents a block of assembly instructions that can be compiled to
  645. machine code or inlined into another AssemblyBlock with addBlock(...).
  646. */
  647. class AssemblyBlock
  648. {
  649. private:
  650. RCArray<Instruction> instructions;
  651. int inlineIndex;
  652. void* compiledCode;
  653. #ifndef WIN32
  654. int compiledSize;
  655. #endif
  656. public:
  657. DLLEXPORT AssemblyBlock();
  658. DLLEXPORT ~AssemblyBlock();
  659. /**
  660. * adds an instruction.
  661. *
  662. * \param instr the instruction to add.
  663. */
  664. DLLEXPORT void addInstruction(Instruction* instr);
  665. /**
  666. * defines a new jump target label.
  667. *
  668. * \param name the name of the label.
  669. */
  670. DLLEXPORT void defineJumpTarget(Text name);
  671. /**
  672. * adds a jump instruction that jumps to the next Instaruction after
  673. * the definition of the given label.
  674. *
  675. * \param jumpOp the op code of the jump iperation.
  676. * \param targetName the label to jump to.
  677. */
  678. DLLEXPORT void addJump(Operation jumpOp, Text targetName);
  679. /**
  680. * adds the value of the source register to the value of the target
  681. * register and stores the result in the target register. single
  682. * operation.
  683. *
  684. * \param target the target register
  685. * \param source the source register
  686. * \param part the register part
  687. */
  688. DLLEXPORT void addAddition(GPRegister target,
  689. GPRegister source,
  690. GPRegisterPart part = FULL64);
  691. /**
  692. * adds the given value to the given part of the target
  693. * register and stores the result in the given part of the target
  694. * register. single operation.
  695. *
  696. * \param target the target register
  697. * \param value the value to add
  698. * \param part the target register part
  699. */
  700. DLLEXPORT void addAddition(
  701. GPRegister target, char value, GPRegisterPart part = LOWER8);
  702. /**
  703. * adds the given value to the given part of the target
  704. * register and stores the result in the given part of the target
  705. * register. single operation.
  706. *
  707. * \param target the target register
  708. * \param value the value to add
  709. * \param part the target register part (only LOWER32 or FULL64 are
  710. * valid)
  711. */
  712. DLLEXPORT void addAddition(
  713. GPRegister target, int value, GPRegisterPart part = LOWER32);
  714. /**
  715. * adds the value of the source register to the value of the target
  716. * register and stores the result in the target register. single
  717. * operation.
  718. *
  719. * \param target the target register
  720. * \param source the source register
  721. * \param type the data type stored in the registers
  722. * \param part the register part
  723. */
  724. DLLEXPORT void addAddition(FPRegister target,
  725. FPRegister source,
  726. FPDataType type,
  727. FPRegisterPart part = Y);
  728. /**
  729. * subtracts the value of the source register from the value of the
  730. * target register and stores the result in the target register.
  731. * single operation.
  732. *
  733. * \param target the target register
  734. * \param source the source register
  735. * \param part the register part
  736. */
  737. DLLEXPORT void addSubtraction(GPRegister target,
  738. GPRegister source,
  739. GPRegisterPart part = FULL64);
  740. /**
  741. * subtracts the given value from the target register and stores the
  742. * result in the target register. single operation.
  743. *
  744. * \param target the target register
  745. * \param value the value to subtract
  746. * \param part the register part
  747. */
  748. DLLEXPORT void addSubtraction(
  749. GPRegister target, char value, GPRegisterPart part = LOWER8);
  750. /**
  751. * subtracts the given value from the target register and stores the
  752. * result in the target register. single operation.
  753. *
  754. * \param target the target register
  755. * \param value the value to subtract
  756. * \param part the register part
  757. */
  758. DLLEXPORT void addSubtraction(
  759. GPRegister target, int value, GPRegisterPart part = LOWER32);
  760. /**
  761. * subtracts the value of the target register from the value of the
  762. * source register and stores the result in the target register.
  763. * single operation.
  764. *
  765. * \param target the target register
  766. * \param source the source register
  767. * \param type the data type stored in the registers
  768. * \param part the register part
  769. */
  770. DLLEXPORT void addSubtraction(FPRegister target,
  771. FPRegister source,
  772. FPDataType type,
  773. FPRegisterPart part = Y);
  774. /**
  775. * multiplies the value of the source register to the value of the
  776. * target register and stores the result in the target register.
  777. * single operation.
  778. *
  779. * \param target the target register
  780. * \param source the source register
  781. * \param part the register part
  782. */
  783. DLLEXPORT void addMultiplication(GPRegister target,
  784. GPRegister source,
  785. GPRegisterPart part = FULL64);
  786. /**
  787. * multiplies the value of the source register to the value of the
  788. * target register and stores the result in the target register.
  789. * single operation.
  790. *
  791. * \param target the target register
  792. * \param source the source register
  793. * \param type the data type stored in the registers
  794. * \param part the register part
  795. */
  796. DLLEXPORT void addMultiplication(FPRegister target,
  797. FPRegister source,
  798. FPDataType type,
  799. FPRegisterPart part = Y);
  800. /**
  801. * devides the value of the target register by the value of the
  802. * source register and stores the result in the target register.
  803. * single operation.
  804. *
  805. * \param target the target register
  806. * \param source the source register
  807. * \param part the register part
  808. */
  809. DLLEXPORT void addDivision(GPRegister target,
  810. GPRegister source,
  811. GPRegisterPart part = FULL64);
  812. /**
  813. * devides the value of the target register by the value of the
  814. * source register and stores the result in the target register.
  815. * single operation.
  816. *
  817. * \param target the target register
  818. * \param source the source register
  819. * \param type the data type stored in the registers
  820. * \param part the register part
  821. */
  822. DLLEXPORT void addDivision(FPRegister target,
  823. FPRegister source,
  824. FPDataType type,
  825. FPRegisterPart part = Y);
  826. /**
  827. * performes bitwise AND without storing the result. only
  828. * SpecialRegister.FLAGS (SF, ZF, PF) is affected. Single operation.
  829. *
  830. * \param r1 the first value
  831. * \param r2 the second value
  832. * \param part the part of the values to test
  833. */
  834. DLLEXPORT void addTest(
  835. GPRegister r1, GPRegister r2, GPRegisterPart part = FULL64);
  836. /**
  837. * subtracts the value of r2 from r1 and sets FLAGS (CF, OF, SF, ZF,
  838. * AF, PF) according to the result. The result is discarded.
  839. *
  840. * \param r1 the first value
  841. * \param r2 the second value
  842. * \param part the part of the values to compare
  843. */
  844. DLLEXPORT void addCompare(
  845. GPRegister r1, GPRegister r2, GPRegisterPart part = FULL64);
  846. /**
  847. * subtracts the value from r1 and sets FLAGS (CF, OF, SF, ZF,
  848. * AF, PF) according to the result. The result is discarded.
  849. *
  850. * \param r1 the first value
  851. * \param value the value to subtract
  852. */
  853. DLLEXPORT void addCompare(GPRegister r1, char value);
  854. /**
  855. * subtracts the value from r1 and sets FLAGS (CF, OF, SF, ZF,
  856. * AF, PF) according to the result. The result is discarded.
  857. *
  858. * \param r1 the first value
  859. * \param value the value to subtract
  860. */
  861. DLLEXPORT void addCompare(GPRegister r1, short value);
  862. /**
  863. * subtracts the value from r1 and sets FLAGS (CF, OF, SF, ZF,
  864. * AF, PF) according to the result. The result is discarded.
  865. *
  866. * \param r1 the first value
  867. * \param value the value to subtract
  868. */
  869. DLLEXPORT void addCompare(GPRegister r1, int value);
  870. /**
  871. * subtracts the value of r2 from r1 and sets FLAGS (ZF, PF, CF).
  872. * the result is discarded
  873. *
  874. * UNORDERED: ZF,PF,CF := 111;
  875. * GREATER_THAN: ZF,PF,CF := 000;
  876. * LESS_THAN: ZF,PF,CF := 001;
  877. * EUAL: ZF,PF,CF := 100;
  878. *
  879. * \param r1 the first value
  880. * \param r2 the second value
  881. * \param type the datatype to compare. only SINGLE types are valid
  882. */
  883. DLLEXPORT void addCompare(
  884. FPRegister r1, FPRegister r2, FPDataType type);
  885. /**
  886. * computes bitwise AND for the values in source and target
  887. * register and stores the result in the target register. single
  888. * operation
  889. *
  890. * \param target the target register
  891. * \param source the source register
  892. * \param part the register part
  893. */
  894. DLLEXPORT void addAnd(GPRegister target,
  895. GPRegister source,
  896. GPRegisterPart part = FULL64);
  897. /**
  898. * computes bitwise AND for the values in source and target register
  899. * and stores the result in the target register. single operation
  900. *
  901. * \param target the target register
  902. * \param source the source register
  903. * \param part the register part
  904. */
  905. DLLEXPORT void addOr(GPRegister target,
  906. GPRegister source,
  907. GPRegisterPart part = FULL64);
  908. /**
  909. * writes the value at the specified valueAddress pointer into a
  910. * register.
  911. *
  912. * \param valueAddress the pointer to the value
  913. * \param target the register where the value should be stored
  914. */
  915. DLLEXPORT void addLoadValue(char* valueAddress, GPRegister target);
  916. /**
  917. * writes the value at the specified valueAddress pointer into a
  918. * register.
  919. *
  920. * \param valueAddress the pointer to the value
  921. * \param target the register where the value should be stored
  922. */
  923. DLLEXPORT void addLoadValue(short* valueAddress, GPRegister target);
  924. /**
  925. * writes the value at the specified valueAddress pointer into a
  926. * register.
  927. *
  928. * \param valueAddress the pointer to the value
  929. * \param target the register where the value should be stored
  930. */
  931. DLLEXPORT void addLoadValue(int* valueAddress, GPRegister target);
  932. /**
  933. * writes the value at the specified valueAddress pointer into a
  934. * register.
  935. *
  936. * \param valueAddress the pointer to the value
  937. * \param target the register where the value should be stored
  938. */
  939. DLLEXPORT void addLoadValue(
  940. __int64* valueAddress, GPRegister target);
  941. /**
  942. * loads the value at the address stored in addressRegister into the
  943. * target register. Single operation.
  944. *
  945. * \param addressRegister a register that contains a memory address
  946. * \param target the target register to store the value into
  947. * \param targetPart the part of the target register that will be
  948. * written to
  949. */
  950. DLLEXPORT void addLoadValue(GPRegister addressRegister,
  951. GPRegister target,
  952. GPRegisterPart targetPart,
  953. int offset = 0);
  954. /**
  955. * writes the specified valueAddress pointer into a register.
  956. *
  957. * \param valueAddress the pointer to the value witch address should
  958. * be stored
  959. * \param target the register where the address should be stored
  960. */
  961. DLLEXPORT void addLoadValue(
  962. float* valueAddress, FPRegister target, GPRegister temp = RAX);
  963. /**
  964. * writes the specified valueAddress pointer into a register.
  965. *
  966. * \param valueAddress the pointer to the value witch address should
  967. * be stored
  968. * \param target the register where the address should be stored
  969. */
  970. DLLEXPORT void addLoadValue(
  971. double* valueAddress, FPRegister target, GPRegister temp = RAX);
  972. /**
  973. * loads a memory address into a register. Single operation.
  974. *
  975. * \param addr the address to load
  976. * \param target the register where the address should be stored
  977. */
  978. template<typename T>
  979. DLLEXPORT void addLoadAddress(T* addr, GPRegister target = RAX)
  980. {
  981. instructions.add(new Instruction(MOV,
  982. {new GPRegisterArgument(target),
  983. new ConstantArgument(
  984. reinterpret_cast<__int64>(addr))}));
  985. }
  986. /**
  987. * moves the given value to LOWER8 bits of target register.
  988. *
  989. * \param target the register to move the value to
  990. * \param value the value to move
  991. */
  992. DLLEXPORT void addMoveValue(GPRegister target, char value);
  993. /**
  994. * moves the given value to LOWER16 bits of target register.
  995. *
  996. * \param target the register to move the value to
  997. * \param value the value to move
  998. */
  999. DLLEXPORT void addMoveValue(GPRegister target, short value);
  1000. /**
  1001. * moves the given value to LOWER32 bits of target register.
  1002. *
  1003. * \param target the register to move the value to
  1004. * \param value the value to move
  1005. */
  1006. DLLEXPORT void addMoveValue(GPRegister target, int value);
  1007. /**
  1008. * moves the given value to LOWER64 bits of target register.
  1009. *
  1010. * \param target the register to move the value to
  1011. * \param value the value to move
  1012. */
  1013. DLLEXPORT void addMoveValue(GPRegister target, __int64 value);
  1014. /**
  1015. * moves the given value to LOWER32 bits of target register.
  1016. * The value needs to be temporarily pushed to the stack, so
  1017. * addLoadValue should be used if performance is critical.
  1018. *
  1019. * \param target the register to move the value to
  1020. * \param value the value to move
  1021. * \param temp temporary register that can be used us store the
  1022. * value
  1023. */
  1024. DLLEXPORT void addMoveValue(
  1025. FPRegister target, float value, GPRegister temp = RAX);
  1026. /**
  1027. * moves the given value to LOWER64 bits of target register.
  1028. * The value needs to be temporarily pushed to the stack, so
  1029. * addLoadValue should be used if performance is critical.
  1030. *
  1031. * \param target the register to move the value to
  1032. * \param value the value to move
  1033. * \param temp temporary register that can be used us store the
  1034. * value
  1035. */
  1036. DLLEXPORT void addMoveValue(
  1037. FPRegister target, double value, GPRegister temp = RAX);
  1038. /**
  1039. * moves the value from source register to target register.
  1040. *
  1041. * \param target the register to move the value to
  1042. * \param source the register to move the value from
  1043. * \param part the part of the register to move
  1044. */
  1045. DLLEXPORT void addMoveValue(GPRegister target,
  1046. GPRegister source,
  1047. GPRegisterPart part = FULL64);
  1048. /**
  1049. * moves the value from source register to target register.
  1050. *
  1051. * \param target the register to move the value to
  1052. * \param source the register to move the value from
  1053. * \param part the part of the register to move
  1054. */
  1055. DLLEXPORT void addMoveValue(FPRegister target,
  1056. FPRegister source,
  1057. FPDataType type,
  1058. FPRegisterPart part = Y);
  1059. /**
  1060. * converts a floating point value from source register into a
  1061. * signed integer value and writes it into the target register.
  1062. * Single operation.
  1063. *
  1064. * \param target the target register
  1065. * \param source the source register
  1066. * \param type the datatype of the source register. Only SINGLE
  1067. * types are valid.
  1068. * \param targetPart the register part to write the result into.
  1069. * Only LOWER32 or FULL64 are valid.
  1070. * \param round if true the value is rounded acourding to bits 13
  1071. * and 14 of the MXCSR register value
  1072. */
  1073. DLLEXPORT void addConversion(GPRegister target,
  1074. FPRegister source,
  1075. FPDataType type,
  1076. GPRegisterPart targetPart,
  1077. bool round = 0);
  1078. /**
  1079. * converts a signed integer from source register into a floating
  1080. * point value and writes it into the target register. Single
  1081. * operation
  1082. *
  1083. * \param target the target register
  1084. * \param source the source register
  1085. * \param targetType the data type after the conversion. Only SINGLE
  1086. * types are valid.
  1087. * \param sourcePart the register part that contains the signed
  1088. * integer. Only LOWER32 and FULL64 are valid.
  1089. */
  1090. DLLEXPORT void addConversion(FPRegister target,
  1091. GPRegister source,
  1092. FPDataType targetType,
  1093. GPRegisterPart sourcePart);
  1094. /**
  1095. * calls a function at a specified memory address.
  1096. *
  1097. * \param functionAddress pointet to the address of the function to
  1098. * call
  1099. * \param gpParams must be the the every n-th entry of the register
  1100. * list (RCX, RDX, R8, R9) for each n-th function parameter that is
  1101. * of type integer
  1102. * \param fpParams must be the the every n-th entry of the register
  1103. * list (MM0, MM1, MM2, MM3) for each n-th function parameter that
  1104. * is of type float/double
  1105. * \param temp temporary register to store the address of the
  1106. * function
  1107. * \param bpTemp temporary register to store the stack pointer
  1108. * before ligning the stack pointer to a 16 byte boundry. The stack
  1109. * pointer will be automatically restored after the function call
  1110. * using the value of this register. A non-volatile register must be
  1111. * used.
  1112. */
  1113. DLLEXPORT void addCall(void* functionAddress,
  1114. FuncReturnType returnType = NO_VALUE,
  1115. std::initializer_list<GPRegister> gpParams = {},
  1116. std::initializer_list<FPRegister> fpParams = {},
  1117. GPRegister temp = RAX,
  1118. GPRegister bpTemp = RBP);
  1119. /**
  1120. * calls a function at a specified memory address.
  1121. *
  1122. * \param functionAddress pointet to the address of the function to
  1123. * call
  1124. * \param gpParams must be the the every n-th entry of the register
  1125. * list (RCX, RDX, R8, R9) for each n-th function parameter that is
  1126. * of type integer
  1127. * \param fpParams must be the the every n-th entry of the register
  1128. * list (MM0, MM1, MM2, MM3) for each n-th function parameter that
  1129. * is of type float/double
  1130. * \param temp temporary register to store the address of the
  1131. * function
  1132. * \param bpTemp temporary register to store the stack pointer
  1133. * before ligning the stack pointer to a 16 byte boundry. The stack
  1134. * pointer will be automatically restored after the function call
  1135. * using the value of this register. A non-volatile register must be
  1136. * used.
  1137. */
  1138. template<typename T>
  1139. DLLEXPORT void addMemberCall(T&& functionAddress,
  1140. FuncReturnType returnType = NO_VALUE,
  1141. std::initializer_list<GPRegister> gpParams = {},
  1142. std::initializer_list<FPRegister> fpParams = {},
  1143. GPRegister temp = RAX,
  1144. GPRegister bpTemp = RBP)
  1145. {
  1146. addCall((void*&)functionAddress,
  1147. returnType,
  1148. gpParams,
  1149. fpParams,
  1150. temp,
  1151. bpTemp);
  1152. }
  1153. /**
  1154. * returns from executing the compiled assembly function.
  1155. */
  1156. DLLEXPORT void addReturn();
  1157. /**
  1158. * pushes a register into the stack.
  1159. *
  1160. * \param reg the register to push
  1161. * \param part the part of the register to push
  1162. */
  1163. DLLEXPORT void addPush(
  1164. GPRegister reg, GPRegisterPart part = FULL64);
  1165. /**
  1166. * pops a value from the sack into a specified register.
  1167. *
  1168. * \param reg the register to store the popped value
  1169. * \param part the part of the register to store the popped value
  1170. */
  1171. DLLEXPORT void addPop(GPRegister reg, GPRegisterPart part = FULL64);
  1172. /**
  1173. * pushes a register into the stack.
  1174. *
  1175. * \param reg the register to push
  1176. * \param type the datatype of the register
  1177. * \param part the part of the register
  1178. */
  1179. DLLEXPORT void addPush(
  1180. FPRegister reg, FPDataType type, FPRegisterPart part = X);
  1181. /**
  1182. * pops a value from the sack into a specified register.
  1183. *
  1184. * \param reg the register to store the popped value
  1185. * \param type the datatype of the register
  1186. * \param part the part of the register
  1187. */
  1188. DLLEXPORT void addPop(
  1189. FPRegister reg, FPDataType type, FPRegisterPart part = X);
  1190. private:
  1191. DLLEXPORT void addPop(RCArray<Instruction>& instructionList,
  1192. FPRegister reg,
  1193. FPDataType type,
  1194. FPRegisterPart part = X);
  1195. public:
  1196. /**
  1197. * copies the assembly code from a given block of assembly
  1198. * instructions.
  1199. *
  1200. * \param block the block to inline
  1201. * \param preservedGPRegisters the GP registers that should be
  1202. * preserved during the inlined block. if a preserved register is
  1203. * used in the block, it will be replaced by another register or
  1204. * pushed to the stack if no free register is available.
  1205. * \param preservedFPRegisters same as preservedGPRegisters but for
  1206. * FP registers
  1207. * \param preservedFPDataTypes data types of the preserved FP
  1208. * registers used to push them to the stack if needed
  1209. * \param blockResultGpReg if the register this pointer points to
  1210. * should be preserved this pointer will be set to the register that
  1211. * was selected to replace the register during execution of the
  1212. * block. Ignored if 0.
  1213. * \param blockResultFpReg same as blockResultGpReg but for FP
  1214. * Registers
  1215. */
  1216. DLLEXPORT void addBlock(AssemblyBlock* block,
  1217. std::initializer_list<GPRegister> preservedGPRegisters,
  1218. std::initializer_list<FPRegister> preservedFPRegisters,
  1219. std::initializer_list<FPDataType> preservedFPDataTypes,
  1220. GPRegister* blockResultGpReg,
  1221. FPRegister* blockResultFpReg);
  1222. /**
  1223. * checks if this block writes to a specified register.
  1224. *
  1225. * \param reg the register to check
  1226. * \return true if the block writes to the register
  1227. */
  1228. DLLEXPORT bool writesToRegister(GPRegister reg) const;
  1229. /**
  1230. * checks if this block writes to a specified register.
  1231. *
  1232. * \param reg the register to check
  1233. * \return true if the block writes to the register
  1234. */
  1235. DLLEXPORT bool writesToRegister(FPRegister reg) const;
  1236. /**
  1237. * checks if this block reads from a specified register.
  1238. *
  1239. * \param reg the register to check
  1240. * \return true if the block reads from the register
  1241. */
  1242. DLLEXPORT bool readsFromRegister(GPRegister reg) const;
  1243. /**
  1244. * checks if this block reads from a specified register.
  1245. *
  1246. * \param reg the register to check
  1247. * \return true if the block reads from the register
  1248. */
  1249. DLLEXPORT bool readsFromRegister(FPRegister reg) const;
  1250. /**
  1251. * checks if a register can be replaced by another register.
  1252. *
  1253. * \param oldReg the register to replace
  1254. * \param newReg the register to use instead
  1255. * \return true if the replacement is possible
  1256. */
  1257. DLLEXPORT bool isReplacementPossible(
  1258. GPRegister oldReg, GPRegister newReg) const;
  1259. /**
  1260. * checks if a register can be replaced by another register.
  1261. *
  1262. * \param oldReg the register to replace
  1263. * \param newReg the register to use instead
  1264. * \return true if the replacement is possible
  1265. */
  1266. DLLEXPORT bool isReplacementPossible(
  1267. FPRegister oldReg, FPRegister newReg) const;
  1268. /**
  1269. * replaces a register with another register.
  1270. *
  1271. * \param oldReg the register to replace
  1272. * \param newReg the register to use instead
  1273. */
  1274. DLLEXPORT void replaceRegister(
  1275. GPRegister oldReg, GPRegister newReg);
  1276. /**
  1277. * replaces a register with another register.
  1278. *
  1279. * \param oldReg the register to replace
  1280. * \param newReg the register to use instead
  1281. */
  1282. DLLEXPORT void replaceRegister(
  1283. FPRegister oldReg, FPRegister newReg);
  1284. /**
  1285. * adds a prefix to all jump labels in this block to avoid conflicts
  1286. * if this block is inlined into another block.
  1287. *
  1288. * \param labelPrefix the label prefix to add
  1289. */
  1290. DLLEXPORT void addJumpLabelPrefix(Text labelPrefix);
  1291. /**
  1292. * \return the instructions of this block
  1293. */
  1294. DLLEXPORT const RCArray<Instruction>& getInstructions() const;
  1295. /**
  1296. * performs optimisations to shorten the needed instructions.
  1297. *
  1298. */
  1299. DLLEXPORT void optimize();
  1300. /**
  1301. * \return a pointer to a function that contains the compiled byte
  1302. * code of this assembly block. and can be called directly with
  1303. * reinterpret_cast<returnType(*)(parameterTypes...)>(compile())(parameters...)
  1304. */
  1305. DLLEXPORT void* compile();
  1306. /**
  1307. * \return a pointer to a function that contains the compiled byte
  1308. * code of this assembly block. and can be called directly with
  1309. */
  1310. template<typename T> DLLEXPORT T compileToFunction()
  1311. {
  1312. return reinterpret_cast<T>(compile());
  1313. }
  1314. };
  1315. } // namespace Assembly
  1316. } // namespace Framework