asm.inc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  1. // Copyright (C) 2012 Zeex
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a
  4. // copy of this software and associated documentation files (the "Software"),
  5. // to deal in the Software without restriction, including without limitation
  6. // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  7. // and/or sell copies of the Software, and to permit persons to whom the
  8. // Software is furnished to do so, subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in
  11. // all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  14. // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  18. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  19. // DEALINGS IN THE SOFTWARE.
  20. #if defined ASM_INC
  21. #endinput
  22. #endif
  23. #define ASM_INC
  24. #include "amx_base"
  25. #include "amx_header"
  26. #include "amx_memory"
  27. #include "asm_macros"
  28. #include "dynamic_call"
  29. #include "opcode"
  30. enum AsmError {
  31. ASM_ERROR_NONE,
  32. ASM_ERROR_OPCODE,
  33. ASM_ERROR_OPERAND,
  34. ASM_ERROR_SPACE,
  35. };
  36. enum AsmContext {
  37. AsmContext_buffer,
  38. AsmContext_buffer_size,
  39. AsmContext_buffer_offset,
  40. AsmContext_error,
  41. AsmContext_error_handler, // ErrorHandler(ctx[AsmContext])
  42. };
  43. stock const ASM_ARGUMENTS_OFFSET = 0x0C;
  44. stock const ASM_LOCALS_OFFSET = -0x04;
  45. stock const ASM_CALLER_FRAME_OFFSET = 0x00;
  46. stock const ASM_RETURN_ADDR_OFFSET = 0x04;
  47. stock const ASM_CTRL_COD = 0;
  48. stock const ASM_CTRL_DAT = 1;
  49. stock const ASM_CTRL_HEA = 2;
  50. stock const ASM_CTRL_STP = 3;
  51. stock const ASM_CTRL_STK = 4;
  52. stock const ASM_CTRL_FRM = 5;
  53. stock const ASM_CTRL_CIP = 6;
  54. static gPreviousWriteOffset = cellmin;
  55. // Internal functions:
  56. static stock AsmError:AsmRaiseError(ctx[AsmContext], AsmError:error) {
  57. if (error != ASM_ERROR_NONE) {
  58. AsmSetError(ctx, error);
  59. if (ctx[AsmContext_error_handler] != 0) {
  60. CallFunction(ctx[AsmContext_error_handler], ref(ctx));
  61. }
  62. }
  63. return error;
  64. }
  65. static stock AsmError:AsmEmitCell(ctx[AsmContext], value) {
  66. if (ctx[AsmContext_buffer_offset] >= ctx[AsmContext_buffer_size]) {
  67. return AsmRaiseError(ctx, ASM_ERROR_SPACE);
  68. }
  69. WriteAmxMemory(ctx[AsmContext_buffer] + ctx[AsmContext_buffer_offset], value);
  70. ctx[AsmContext_buffer_offset] += 4;
  71. return ASM_ERROR_NONE;
  72. }
  73. static stock AsmError:AsmEmitOpcode(ctx[AsmContext], Opcode:opcode) {
  74. if (opcode <= OP_NONE || _:opcode >= NUM_OPCODES) {
  75. return AsmRaiseError(ctx, ASM_ERROR_OPCODE);
  76. }
  77. return AsmEmitCell(ctx, _:RelocateOpcode(opcode));
  78. }
  79. static stock AsmError:AsmEmitOperand(ctx[AsmContext], value) {
  80. return AsmEmitCell(ctx, value);
  81. }
  82. static stock AsmError:AsmEmitInstruction(ctx[AsmContext], Opcode:opcode, ...) {
  83. // if there's an error while writing then backtracking is useful
  84. gPreviousWriteOffset = ctx[AsmContext_buffer_offset];
  85. new AsmError:error = ASM_ERROR_NONE;
  86. error = AsmEmitOpcode(ctx, opcode);
  87. if (error != ASM_ERROR_NONE) {
  88. return error;
  89. }
  90. static const STATIC_ARGS = 2;
  91. new num_opers = numargs() - STATIC_ARGS;
  92. for (new i = 0; i < num_opers; i++) {
  93. error = AsmEmitOperand(ctx, getarg(STATIC_ARGS + i));
  94. if (error != ASM_ERROR_NONE) {
  95. return error;
  96. }
  97. }
  98. return ASM_ERROR_NONE;
  99. }
  100. static stock AsmGetJumpAddressFromOffset(ctx[AsmContext], offset) {
  101. new amxhdr[AMX_HDR];
  102. GetAmxHeader(amxhdr);
  103. new next_offset = 2 * 4; // offset to the next instruction
  104. new base = GetAmxBaseAddress() + amxhdr[AMX_HDR_DAT];
  105. new dest = ctx[AsmContext_buffer] + ctx[AsmContext_buffer_offset] + next_offset + offset;
  106. return base + dest;
  107. }
  108. static stock AsmError:AsmEmitJumpInstruction(ctx[AsmContext], Opcode:opcode, offset) {
  109. return AsmEmitInstruction(ctx, opcode, AsmGetJumpAddressFromOffset(ctx, offset));
  110. }
  111. // Core functions:
  112. stock AsmError:AsmInitPtr(ctx[AsmContext], buffer, size) {
  113. ctx[AsmContext_buffer] = buffer;
  114. ctx[AsmContext_buffer_size] = size;
  115. ctx[AsmContext_buffer_offset] = 0;
  116. ctx[AsmContext_error_handler] = 0;
  117. return ASM_ERROR_NONE;
  118. }
  119. stock AsmGetPreviousWriteOffset() {
  120. return gPreviousWriteOffset;
  121. }
  122. stock AsmGetBufferSize(ctx[AsmContext]) {
  123. return ctx[AsmContext_buffer_size] - ctx[AsmContext_buffer_offset];
  124. }
  125. stock AsmError:AsmInit(ctx[AsmContext], buffer[], size = sizeof(buffer)) {
  126. AsmInitPtr(ctx, ref(buffer), size * 4);
  127. }
  128. stock AsmGetCode(const ctx[AsmContext]) {
  129. new amxhdr[AMX_HDR];
  130. GetAmxHeader(amxhdr);
  131. return ctx[AsmContext_buffer] + amxhdr[AMX_HDR_DAT] - amxhdr[AMX_HDR_COD];
  132. }
  133. stock AsmGetCodeSize(const ctx[AsmContext]) {
  134. return ctx[AsmContext_buffer_offset];
  135. }
  136. stock AsmError:AsmGetError(ctx[AsmContext]) {
  137. return AsmError:ctx[AsmContext_error];
  138. }
  139. stock AsmSetError(ctx[AsmContext], AsmError:error) {
  140. ctx[AsmContext_error] = _:error;
  141. }
  142. stock AsmClearError(ctx[AsmContext]) {
  143. AsmSetError(ctx, ASM_ERROR_NONE);
  144. }
  145. stock AsmGetErrorHandler(const ctx[AsmContext]) {
  146. return ctx[AsmContext_error_handler];
  147. }
  148. stock AsmError:AsmSetErrorHandler(ctx[AsmContext], error_handler) {
  149. ctx[AsmContext_error_handler] = error_handler;
  150. return ASM_ERROR_NONE;
  151. }
  152. // Low level functions:
  153. stock AsmError:AsmEmitAdd(ctx[AsmContext]) {
  154. return AsmEmitInstruction(ctx, OP_ADD);
  155. }
  156. stock AsmError:AsmEmitAddC(ctx[AsmContext], value) {
  157. return AsmEmitInstruction(ctx, OP_ADD_C, value);
  158. }
  159. stock AsmError:AsmEmitAddrAlt(ctx[AsmContext], offset) {
  160. return AsmEmitInstruction(ctx, OP_ADDR_ALT, offset);
  161. }
  162. stock AsmError:AsmEmitAddrPri(ctx[AsmContext], offset) {
  163. return AsmEmitInstruction(ctx, OP_ADDR_PRI, offset);
  164. }
  165. stock AsmError:AsmEmitAlignAlt(ctx[AsmContext], number) {
  166. return AsmEmitInstruction(ctx, OP_ALIGN_ALT, number);
  167. }
  168. stock AsmError:AsmEmitAlignPri(ctx[AsmContext], number) {
  169. return AsmEmitInstruction(ctx, OP_ALIGN_PRI, number);
  170. }
  171. stock AsmError:AsmEmitAnd(ctx[AsmContext]) {
  172. return AsmEmitInstruction(ctx, OP_AND);
  173. }
  174. stock AsmError:AsmEmitBounds(ctx[AsmContext], bound) {
  175. return AsmEmitInstruction(ctx, OP_BOUDNS, bound);
  176. }
  177. stock AsmError:AsmEmitBreak(ctx[AsmContext]) {
  178. return AsmEmitInstruction(ctx, OP_BREAK);
  179. }
  180. stock AsmError:AsmEmitCall(ctx[AsmContext], address) {
  181. return AsmEmitInstruction(ctx, OP_CALL, address);
  182. }
  183. stock AsmError:AsmEmitCmps(ctx[AsmContext], nbytes) {
  184. return AsmEmitInstruction(ctx, OP_CMPS, nbytes);
  185. }
  186. stock AsmError:AsmEmitConstAlt(ctx[AsmContext], value) {
  187. return AsmEmitInstruction(ctx, OP_CONST_ALT, value);
  188. }
  189. stock AsmError:AsmEmitConstPri(ctx[AsmContext], value) {
  190. return AsmEmitInstruction(ctx, OP_CONST_PRI, value);
  191. }
  192. stock AsmError:AsmEmitDec(ctx[AsmContext], address) {
  193. return AsmEmitInstruction(ctx, OP_DEC, address);
  194. }
  195. stock AsmError:AsmEmitDecAlt(ctx[AsmContext]) {
  196. return AsmEmitInstruction(ctx, OP_DEC_ALT);
  197. }
  198. stock AsmError:AsmEmitDecI(ctx[AsmContext]) {
  199. return AsmEmitInstruction(ctx, OP_DEC_I);
  200. }
  201. stock AsmError:AsmEmitDecPri(ctx[AsmContext]) {
  202. return AsmEmitInstruction(ctx, OP_DEC_PRI);
  203. }
  204. stock AsmError:AsmEmitDecS(ctx[AsmContext], offset) {
  205. return AsmEmitInstruction(ctx, OP_DEC_S, offset);
  206. }
  207. stock AsmError:AsmEmitEq(ctx[AsmContext]) {
  208. return AsmEmitInstruction(ctx, OP_EQ);
  209. }
  210. stock AsmError:AsmEmitEqCAlt(ctx[AsmContext], value) {
  211. return AsmEmitInstruction(ctx, OP_EQ_C_ALT, value);
  212. }
  213. stock AsmError:AsmEmitEqCPri(ctx[AsmContext], value) {
  214. return AsmEmitInstruction(ctx, OP_EQ_C_PRI, value);
  215. }
  216. stock AsmError:AsmEmitFill(ctx[AsmContext], nbytes) {
  217. return AsmEmitInstruction(ctx, OP_FILL, nbytes);
  218. }
  219. stock AsmError:AsmEmitGeq(ctx[AsmContext]) {
  220. return AsmEmitInstruction(ctx, OP_GEQ);
  221. }
  222. stock AsmError:AsmEmitGrtr(ctx[AsmContext]) {
  223. return AsmEmitInstruction(ctx, OP_GRTR);
  224. }
  225. stock AsmError:AsmEmitHalt(ctx[AsmContext], code) {
  226. return AsmEmitInstruction(ctx, OP_HALT, code);
  227. }
  228. stock AsmError:AsmEmitHeap(ctx[AsmContext], nbytes) {
  229. return AsmEmitInstruction(ctx, OP_HEAP, nbytes);
  230. }
  231. stock AsmError:AsmEmitIdxaddr(ctx[AsmContext]) {
  232. return AsmEmitInstruction(ctx, OP_IDXADDR);
  233. }
  234. stock AsmError:AsmEmitIdxaddrB(ctx[AsmContext], shift) {
  235. return AsmEmitInstruction(ctx, OP_IDXADDR_B, shift);
  236. }
  237. stock AsmError:AsmEmitInc(ctx[AsmContext], address) {
  238. return AsmEmitInstruction(ctx, OP_INC, address);
  239. }
  240. stock AsmError:AsmEmitIncAlt(ctx[AsmContext]) {
  241. return AsmEmitInstruction(ctx, OP_INC_ALT);
  242. }
  243. stock AsmError:AsmEmitIncI(ctx[AsmContext]) {
  244. return AsmEmitInstruction(ctx, OP_INC_I);
  245. }
  246. stock AsmError:AsmEmitIncPri(ctx[AsmContext]) {
  247. return AsmEmitInstruction(ctx, OP_INC_PRI);
  248. }
  249. stock AsmError:AsmEmitIncS(ctx[AsmContext], offset) {
  250. return AsmEmitInstruction(ctx, OP_INC_S, offset);
  251. }
  252. stock AsmError:AsmEmitInvert(ctx[AsmContext]) {
  253. return AsmEmitInstruction(ctx, OP_INVERT);
  254. }
  255. stock AsmError:AsmEmitJeq(ctx[AsmContext], address) {
  256. return AsmEmitInstruction(ctx, OP_JEQ, address);
  257. }
  258. stock AsmError:AsmEmitJeqRel(ctx[AsmContext], offset) {
  259. return AsmEmitJumpInstruction(ctx, OP_JEQ, offset);
  260. }
  261. stock AsmError:AsmEmitJgeq(ctx[AsmContext], address) {
  262. return AsmEmitInstruction(ctx, OP_JGEQ, address);
  263. }
  264. stock AsmError:AsmEmitJgeqRel(ctx[AsmContext], offset) {
  265. return AsmEmitJumpInstruction(ctx, OP_JGEQ, offset);
  266. }
  267. stock AsmError:AsmEmitJgrtr(ctx[AsmContext], address) {
  268. return AsmEmitInstruction(ctx, OP_JGRTR, address);
  269. }
  270. stock AsmError:AsmEmitJgrtrRel(ctx[AsmContext], offset) {
  271. return AsmEmitJumpInstruction(ctx, OP_JGRTR, offset);
  272. }
  273. stock AsmError:AsmEmitJleq(ctx[AsmContext], address) {
  274. return AsmEmitInstruction(ctx, OP_JLEQ, address);
  275. }
  276. stock AsmError:AsmEmitJleqRel(ctx[AsmContext], offset) {
  277. return AsmEmitJumpInstruction(ctx, OP_JLEQ, offset);
  278. }
  279. stock AsmError:AsmEmitJless(ctx[AsmContext], address) {
  280. return AsmEmitInstruction(ctx, OP_JLESS, address);
  281. }
  282. stock AsmError:AsmEmitJlessRel(ctx[AsmContext], offset) {
  283. return AsmEmitJumpInstruction(ctx, OP_JLESS, offset);
  284. }
  285. stock AsmError:AsmEmitJneq(ctx[AsmContext], address) {
  286. return AsmEmitInstruction(ctx, OP_JNEQ, address);
  287. }
  288. stock AsmError:AsmEmitJneqRel(ctx[AsmContext], offset) {
  289. return AsmEmitJumpInstruction(ctx, OP_JNEQ, offset);
  290. }
  291. stock AsmError:AsmEmitJnz(ctx[AsmContext], address) {
  292. return AsmEmitInstruction(ctx, OP_JNZ, address);
  293. }
  294. stock AsmError:AsmEmitJnzRel(ctx[AsmContext], offset) {
  295. return AsmEmitJumpInstruction(ctx, OP_JNZ, offset);
  296. }
  297. stock AsmError:AsmEmitJsgeq(ctx[AsmContext], address) {
  298. return AsmEmitInstruction(ctx, OP_JSGEQ, address);
  299. }
  300. stock AsmError:AsmEmitJsgeqRel(ctx[AsmContext], offset) {
  301. return AsmEmitJumpInstruction(ctx, OP_JSGEQ, offset);
  302. }
  303. stock AsmError:AsmEmitJsgrtr(ctx[AsmContext], address) {
  304. return AsmEmitInstruction(ctx, OP_JSTRTR, address);
  305. }
  306. stock AsmError:AsmEmitJsgrtrRel(ctx[AsmContext], offset) {
  307. return AsmEmitJumpInstruction(ctx, OP_JSTRTR, offset);
  308. }
  309. stock AsmError:AsmEmitJsleq(ctx[AsmContext], address) {
  310. return AsmEmitInstruction(ctx, OP_JSLEQ, address);
  311. }
  312. stock AsmError:AsmEmitJsleqRel(ctx[AsmContext], offset) {
  313. return AsmEmitJumpInstruction(ctx, OP_JSLEQ, offset);
  314. }
  315. stock AsmError:AsmEmitJsless(ctx[AsmContext], address) {
  316. return AsmEmitInstruction(ctx, OP_JSLESS, address);
  317. }
  318. stock AsmError:AsmEmitJslessRel(ctx[AsmContext], offset) {
  319. return AsmEmitJumpInstruction(ctx, OP_JSLESS, offset);
  320. }
  321. stock AsmError:AsmEmitJump(ctx[AsmContext], address) {
  322. return AsmEmitInstruction(ctx, OP_JUMP, address);
  323. }
  324. stock AsmError:AsmEmitJumpRel(ctx[AsmContext], offset) {
  325. return AsmEmitJumpInstruction(ctx, OP_JUMP, offset);
  326. }
  327. stock AsmError:AsmEmitJzer(ctx[AsmContext], address) {
  328. return AsmEmitInstruction(ctx, OP_JZER, address);
  329. }
  330. stock AsmError:AsmEmitJzerRel(ctx[AsmContext], offset) {
  331. return AsmEmitJumpInstruction(ctx, OP_JZER, offset);
  332. }
  333. stock AsmError:AsmEmitLctrl(ctx[AsmContext], index) {
  334. assert(index >= 0 && index <= 6);
  335. return AsmEmitInstruction(ctx, OP_LCTRL, index);
  336. }
  337. stock AsmError:AsmEmitLeq(ctx[AsmContext]) {
  338. return AsmEmitInstruction(ctx, OP_LEQ);
  339. }
  340. stock AsmError:AsmEmitLess(ctx[AsmContext]) {
  341. return AsmEmitInstruction(ctx, OP_LESS);
  342. }
  343. stock AsmError:AsmEmitLidx(ctx[AsmContext]) {
  344. return AsmEmitInstruction(ctx, OP_LIDX);
  345. }
  346. stock AsmError:AsmEmitLidxB(ctx[AsmContext], shift) {
  347. return AsmEmitInstruction(ctx, OP_LIDX_B, shift);
  348. }
  349. stock AsmError:AsmEmitLoadAlt(ctx[AsmContext], address) {
  350. return AsmEmitInstruction(ctx, OP_LOAD_ALT, address);
  351. }
  352. stock AsmError:AsmEmitLoadPri(ctx[AsmContext], address) {
  353. return AsmEmitInstruction(ctx, OP_LOAD_PRI, address);
  354. }
  355. stock AsmError:AsmEmitLoad(ctx[AsmContext], address) {
  356. return AsmEmitInstruction(ctx, OP_LOAD_ALT, address);
  357. }
  358. stock AsmError:AsmEmitLoadI(ctx[AsmContext]) {
  359. return AsmEmitInstruction(ctx, OP_LOAD_I);
  360. }
  361. stock AsmError:AsmEmitLoadSAlt(ctx[AsmContext], offset) {
  362. return AsmEmitInstruction(ctx, OP_LOAD_S_ALT, offset);
  363. }
  364. stock AsmError:AsmEmitLoadSPri(ctx[AsmContext], offset) {
  365. return AsmEmitInstruction(ctx, OP_LOAD_S_PRI, offset);
  366. }
  367. stock AsmError:AsmEmitLodbI(ctx[AsmContext], nbytes) {
  368. assert(nbytes == 1 || nbytes == 2 || nbytes == 4);
  369. return AsmEmitInstruction(ctx, OP_LODB_I, nbytes);
  370. }
  371. stock AsmError:AsmEmitLrefAlt(ctx[AsmContext], address) {
  372. return AsmEmitInstruction(ctx, OP_LREF_ALT, address);
  373. }
  374. stock AsmError:AsmEmitLrefPri(ctx[AsmContext], address) {
  375. return AsmEmitInstruction(ctx, OP_LREF_PRI, address);
  376. }
  377. stock AsmError:AsmEmitLrefSAlt(ctx[AsmContext], offset) {
  378. return AsmEmitInstruction(ctx, OP_LREF_S_ALT, offset);
  379. }
  380. stock AsmError:AsmEmitLrefSPri(ctx[AsmContext], offset) {
  381. return AsmEmitInstruction(ctx, OP_LREF_S_PRI, offset);
  382. }
  383. stock AsmError:AsmEmitMoveAlt(ctx[AsmContext]) {
  384. return AsmEmitInstruction(ctx, OP_MOVE_ALT);
  385. }
  386. stock AsmError:AsmEmitMovePri(ctx[AsmContext]) {
  387. return AsmEmitInstruction(ctx, OP_MOVE_PRI);
  388. }
  389. stock AsmError:AsmEmitMovs(ctx[AsmContext], nbytes) {
  390. return AsmEmitInstruction(ctx, OP_MOVS, nbytes);
  391. }
  392. stock AsmError:AsmEmitNeg(ctx[AsmContext]) {
  393. return AsmEmitInstruction(ctx, OP_NEG);
  394. }
  395. stock AsmError:AsmEmitNeq(ctx[AsmContext]) {
  396. return AsmEmitInstruction(ctx, OP_NEQ);
  397. }
  398. stock AsmError:AsmEmitNop(ctx[AsmContext]) {
  399. return AsmEmitInstruction(ctx, OP_NOP);
  400. }
  401. stock AsmError:AsmEmitNot(ctx[AsmContext]) {
  402. return AsmEmitInstruction(ctx, OP_NOT);
  403. }
  404. stock AsmError:AsmEmitOr(ctx[AsmContext]) {
  405. return AsmEmitInstruction(ctx, OP_OR);
  406. }
  407. stock AsmError:AsmEmitPopAlt(ctx[AsmContext]) {
  408. return AsmEmitInstruction(ctx, OP_POP_ALT);
  409. }
  410. stock AsmError:AsmEmitPopPri(ctx[AsmContext]) {
  411. return AsmEmitInstruction(ctx, OP_POP_PRI);
  412. }
  413. stock AsmError:AsmEmitProc(ctx[AsmContext]) {
  414. return AsmEmitInstruction(ctx, OP_PROC);
  415. }
  416. stock AsmError:AsmEmitPushAdr(ctx[AsmContext], offset) {
  417. return AsmEmitInstruction(ctx, OP_PUSH_ADR, offset);
  418. }
  419. stock AsmError:AsmEmitPushAlt(ctx[AsmContext]) {
  420. return AsmEmitInstruction(ctx, OP_PUSH_ALT);
  421. }
  422. stock AsmError:AsmEmitPushC(ctx[AsmContext], value) {
  423. return AsmEmitInstruction(ctx, OP_PUSH_C, value);
  424. }
  425. stock AsmError:AsmEmitPushPri(ctx[AsmContext]) {
  426. return AsmEmitInstruction(ctx, OP_PUSH_PRI);
  427. }
  428. stock AsmError:AsmEmitPush(ctx[AsmContext], address) {
  429. return AsmEmitInstruction(ctx, OP_PUSH, address);
  430. }
  431. stock AsmError:AsmEmitPushS(ctx[AsmContext], offset) {
  432. return AsmEmitInstruction(ctx, OP_PUSH_S, offset);
  433. }
  434. stock AsmError:AsmEmitRet(ctx[AsmContext]) {
  435. return AsmEmitInstruction(ctx, OP_RET);
  436. }
  437. stock AsmError:AsmEmitRetn(ctx[AsmContext]) {
  438. return AsmEmitInstruction(ctx, OP_RETN);
  439. }
  440. stock AsmError:AsmEmitSctrl(ctx[AsmContext], index) {
  441. assert(index == 2 || 4 <= index <= 6);
  442. return AsmEmitInstruction(ctx, OP_SCTRL, index);
  443. }
  444. stock AsmError:AsmEmitSdiv(ctx[AsmContext]) {
  445. return AsmEmitInstruction(ctx, OP_SDIV);
  446. }
  447. stock AsmError:AsmEmitSdivAlt(ctx[AsmContext]) {
  448. return AsmEmitInstruction(ctx, OP_SDIV_ALT);
  449. }
  450. stock AsmError:AsmEmitSgeq(ctx[AsmContext]) {
  451. return AsmEmitInstruction(ctx, OP_SGEQ);
  452. }
  453. stock AsmError:AsmEmitSgrtr(ctx[AsmContext]) {
  454. return AsmEmitInstruction(ctx, OP_SGRTR);
  455. }
  456. stock AsmError:AsmEmitShl(ctx[AsmContext]) {
  457. return AsmEmitInstruction(ctx, OP_SHL);
  458. }
  459. stock AsmError:AsmEmitShlCAlt(ctx[AsmContext], shift) {
  460. return AsmEmitInstruction(ctx, OP_SHL_C_PRI, shift);
  461. }
  462. stock AsmError:AsmEmitShlCPri(ctx[AsmContext], shift) {
  463. return AsmEmitInstruction(ctx, OP_SHL_C_PRI, shift);
  464. }
  465. stock AsmError:AsmEmitShrCAlt(ctx[AsmContext], shift) {
  466. return AsmEmitInstruction(ctx, OP_SHR_C_PRI, shift);
  467. }
  468. stock AsmError:AsmEmitShrCPri(ctx[AsmContext], shift) {
  469. return AsmEmitInstruction(ctx, OP_SHR_C_PRI, shift);
  470. }
  471. stock AsmError:AsmEmitShr(ctx[AsmContext]) {
  472. return AsmEmitInstruction(ctx, OP_SHR);
  473. }
  474. stock AsmError:AsmEmitSignAlt(ctx[AsmContext]) {
  475. return AsmEmitInstruction(ctx, OP_SIGN_ALT);
  476. }
  477. stock AsmError:AsmEmitSignPri(ctx[AsmContext]) {
  478. return AsmEmitInstruction(ctx, OP_SIGN_PRI);
  479. }
  480. stock AsmError:AsmEmitSleq(ctx[AsmContext]) {
  481. return AsmEmitInstruction(ctx, OP_SLEQ);
  482. }
  483. stock AsmError:AsmEmitSless(ctx[AsmContext]) {
  484. return AsmEmitInstruction(ctx, OP_SLESS);
  485. }
  486. stock AsmError:AsmEmitSmul(ctx[AsmContext]) {
  487. return AsmEmitInstruction(ctx, OP_SMUL);
  488. }
  489. stock AsmError:AsmEmitSmulC(ctx[AsmContext], value) {
  490. return AsmEmitInstruction(ctx, OP_SMUL_C, value);
  491. }
  492. stock AsmError:AsmEmitSshr(ctx[AsmContext]) {
  493. return AsmEmitInstruction(ctx, OP_SSHR);
  494. }
  495. stock AsmError:AsmEmitSrefAlt(ctx[AsmContext], address) {
  496. return AsmEmitInstruction(ctx, OP_SREF_ALT, address);
  497. }
  498. stock AsmError:AsmEmitSrefPri(ctx[AsmContext], address) {
  499. return AsmEmitInstruction(ctx, OP_SREF_PRI, address);
  500. }
  501. stock AsmError:AsmEmitSrefSAlt(ctx[AsmContext], offset) {
  502. return AsmEmitInstruction(ctx, OP_SREF_S_ALT, offset);
  503. }
  504. stock AsmError:AsmEmitSrefSPri(ctx[AsmContext], offset) {
  505. return AsmEmitInstruction(ctx, OP_SREF_S_PRI, offset);
  506. }
  507. stock AsmError:AsmEmitStack(ctx[AsmContext], nbytes) {
  508. return AsmEmitInstruction(ctx, OP_STACK, nbytes);
  509. }
  510. stock AsmError:AsmEmitStorAlt(ctx[AsmContext], address) {
  511. return AsmEmitInstruction(ctx, OP_STOR_ALT, address);
  512. }
  513. stock AsmError:AsmEmitStorPri(ctx[AsmContext], address) {
  514. return AsmEmitInstruction(ctx, OP_STOR_PRI, address);
  515. }
  516. stock AsmError:AsmEmitStorI(ctx[AsmContext]) {
  517. return AsmEmitInstruction(ctx, OP_STOR_I);
  518. }
  519. stock AsmError:AsmEmitStorSAlt(ctx[AsmContext], offset) {
  520. return AsmEmitInstruction(ctx, OP_STOR_S_ALT, offset);
  521. }
  522. stock AsmError:AsmEmitStorSPri(ctx[AsmContext], offset) {
  523. return AsmEmitInstruction(ctx, OP_STOR_S_PRI, offset);
  524. }
  525. stock AsmError:AsmEmitStrbI(ctx[AsmContext], nbytes) {
  526. assert(nbytes == 1 || nbytes == 2 || nbytes == 4);
  527. return AsmEmitInstruction(ctx, OP_STRB_I, nbytes);
  528. }
  529. stock AsmError:AsmEmitSub(ctx[AsmContext]) {
  530. return AsmEmitInstruction(ctx, OP_SUB);
  531. }
  532. stock AsmError:AsmEmitSubAlt(ctx[AsmContext]) {
  533. return AsmEmitInstruction(ctx, OP_SUB_ALT);
  534. }
  535. stock AsmError:AsmEmitSwapAlt(ctx[AsmContext]) {
  536. return AsmEmitInstruction(ctx, OP_SWAP_ALT);
  537. }
  538. stock AsmError:AsmEmitSwapPri(ctx[AsmContext]) {
  539. return AsmEmitInstruction(ctx, OP_SWAP_PRI);
  540. }
  541. stock AsmError:AsmEmitSysreqC(ctx[AsmContext], index) {
  542. return AsmEmitInstruction(ctx, OP_SYSREQ_C, index);
  543. }
  544. stock AsmError:AsmEmitSysreqD(ctx[AsmContext], address) {
  545. return AsmEmitInstruction(ctx, OP_SYSREQ_D, address);
  546. }
  547. stock AsmError:AsmEmitSysreqPri(ctx[AsmContext]) {
  548. return AsmEmitInstruction(ctx, OP_SYSREQ_PRI);
  549. }
  550. stock AsmError:AsmEmitUdiv(ctx[AsmContext]) {
  551. return AsmEmitInstruction(ctx, OP_UDIV);
  552. }
  553. stock AsmError:AsmEmitUdivAlt(ctx[AsmContext]) {
  554. return AsmEmitInstruction(ctx, OP_UDIV_ALT);
  555. }
  556. stock AsmError:AsmEmitUmul(ctx[AsmContext]) {
  557. return AsmEmitInstruction(ctx, OP_UMUL);
  558. }
  559. stock AsmError:AsmEmitXchg(ctx[AsmContext]) {
  560. return AsmEmitInstruction(ctx, OP_XCHG);
  561. }
  562. stock AsmError:AsmEmitXor(ctx[AsmContext]) {
  563. return AsmEmitInstruction(ctx, OP_XOR);
  564. }
  565. stock AsmError:AsmEmitZero(ctx[AsmContext], address) {
  566. return AsmEmitInstruction(ctx, OP_ZERO, address);
  567. }
  568. stock AsmError:AsmEmitZeroAlt(ctx[AsmContext]) {
  569. return AsmEmitInstruction(ctx, OP_ZERO_ALT);
  570. }
  571. stock AsmError:AsmEmitZeroPri(ctx[AsmContext]) {
  572. return AsmEmitInstruction(ctx, OP_ZERO_PRI);
  573. }
  574. stock AsmError:AsmEmitZeroS(ctx[AsmContext], offset) {
  575. return AsmEmitInstruction(ctx, OP_ZERO_S, offset);
  576. }
  577. // Higher level functions:
  578. stock AsmError:AsmEmitSysreq(ctx[AsmContext], const name[]) {
  579. return AsmEmitSysreqC(ctx, GetNativeIndexFromName(name));
  580. }
  581. stock AsmError:AsmEmitPopArgs(ctx[AsmContext], n) {
  582. return AsmEmitStack(ctx, (n + 1) * 4);
  583. }
  584. stock AsmError:AsmEmitPushArg(ctx[AsmContext], n) {
  585. return AsmEmitPushS(ctx, AsmGetArgOffset(n));
  586. }
  587. stock AsmError:AsmEmitPushNumArgs(ctx[AsmContext], n) {
  588. return AsmEmitPushC(ctx, 4 * n);
  589. }
  590. // Helpers:
  591. stock AsmGetArgOffset(n) {
  592. return ASM_ARGUMENTS_OFFSET + 4 * n;
  593. }