win64-except.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. /*
  2. * Win64 structured exception handling support
  3. *
  4. * Copyright (C) 2007 Peter Johnson
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
  19. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  20. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  21. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  22. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  23. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  24. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  25. * POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #include <util.h>
  28. #include <libyasm.h>
  29. #include "coff-objfmt.h"
  30. #define UNW_FLAG_EHANDLER 0x01
  31. #define UNW_FLAG_UHANDLER 0x02
  32. #define UNW_FLAG_CHAININFO 0x04
  33. /* Bytecode callback function prototypes */
  34. static void win64_uwinfo_bc_destroy(void *contents);
  35. static void win64_uwinfo_bc_print(const void *contents, FILE *f,
  36. int indent_level);
  37. static void win64_uwinfo_bc_finalize(yasm_bytecode *bc,
  38. yasm_bytecode *prev_bc);
  39. static int win64_uwinfo_bc_calc_len
  40. (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
  41. static int win64_uwinfo_bc_expand(yasm_bytecode *bc, int span, long old_val,
  42. long new_val, /*@out@*/ long *neg_thres,
  43. /*@out@*/ long *pos_thres);
  44. static int win64_uwinfo_bc_tobytes
  45. (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
  46. yasm_output_value_func output_value,
  47. /*@null@*/ yasm_output_reloc_func output_reloc);
  48. static void win64_uwcode_bc_destroy(void *contents);
  49. static void win64_uwcode_bc_print(const void *contents, FILE *f,
  50. int indent_level);
  51. static void win64_uwcode_bc_finalize(yasm_bytecode *bc,
  52. yasm_bytecode *prev_bc);
  53. static int win64_uwcode_bc_calc_len
  54. (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
  55. static int win64_uwcode_bc_expand(yasm_bytecode *bc, int span, long old_val,
  56. long new_val, /*@out@*/ long *neg_thres,
  57. /*@out@*/ long *pos_thres);
  58. static int win64_uwcode_bc_tobytes
  59. (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
  60. yasm_output_value_func output_value,
  61. /*@null@*/ yasm_output_reloc_func output_reloc);
  62. /* Bytecode callback structures */
  63. static const yasm_bytecode_callback win64_uwinfo_bc_callback = {
  64. win64_uwinfo_bc_destroy,
  65. win64_uwinfo_bc_print,
  66. win64_uwinfo_bc_finalize,
  67. NULL,
  68. win64_uwinfo_bc_calc_len,
  69. win64_uwinfo_bc_expand,
  70. win64_uwinfo_bc_tobytes,
  71. 0
  72. };
  73. static const yasm_bytecode_callback win64_uwcode_bc_callback = {
  74. win64_uwcode_bc_destroy,
  75. win64_uwcode_bc_print,
  76. win64_uwcode_bc_finalize,
  77. NULL,
  78. win64_uwcode_bc_calc_len,
  79. win64_uwcode_bc_expand,
  80. win64_uwcode_bc_tobytes,
  81. 0
  82. };
  83. coff_unwind_info *
  84. yasm_win64__uwinfo_create(void)
  85. {
  86. coff_unwind_info *info = yasm_xmalloc(sizeof(coff_unwind_info));
  87. info->proc = NULL;
  88. info->prolog = NULL;
  89. info->ehandler = NULL;
  90. info->framereg = 0;
  91. /* Frameoff is really a 4-bit value, scaled by 16 */
  92. yasm_value_initialize(&info->frameoff, NULL, 8);
  93. SLIST_INIT(&info->codes);
  94. yasm_value_initialize(&info->prolog_size, NULL, 8);
  95. yasm_value_initialize(&info->codes_count, NULL, 8);
  96. return info;
  97. }
  98. void
  99. yasm_win64__uwinfo_destroy(coff_unwind_info *info)
  100. {
  101. coff_unwind_code *code;
  102. yasm_value_delete(&info->frameoff);
  103. yasm_value_delete(&info->prolog_size);
  104. yasm_value_delete(&info->codes_count);
  105. while (!SLIST_EMPTY(&info->codes)) {
  106. code = SLIST_FIRST(&info->codes);
  107. SLIST_REMOVE_HEAD(&info->codes, link);
  108. yasm_value_delete(&code->off);
  109. yasm_xfree(code);
  110. }
  111. yasm_xfree(info);
  112. }
  113. void
  114. yasm_win64__unwind_generate(yasm_section *xdata, coff_unwind_info *info,
  115. unsigned long line)
  116. {
  117. yasm_bytecode *infobc, *codebc = NULL;
  118. coff_unwind_code *code;
  119. /* 4-byte align the start of unwind info */
  120. yasm_section_bcs_append(xdata, yasm_bc_create_align(
  121. yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(4)),
  122. line),
  123. NULL, NULL, NULL, line));
  124. /* Prolog size = end of prolog - start of procedure */
  125. yasm_value_initialize(&info->prolog_size,
  126. yasm_expr_create(YASM_EXPR_SUB, yasm_expr_sym(info->prolog),
  127. yasm_expr_sym(info->proc), line),
  128. 8);
  129. /* Unwind info */
  130. infobc = yasm_bc_create_common(&win64_uwinfo_bc_callback, info, line);
  131. yasm_section_bcs_append(xdata, infobc);
  132. /* Code array */
  133. SLIST_FOREACH(code, &info->codes, link) {
  134. codebc = yasm_bc_create_common(&win64_uwcode_bc_callback, code,
  135. yasm_symrec_get_def_line(code->loc));
  136. yasm_section_bcs_append(xdata, codebc);
  137. }
  138. /* Avoid double-free (by code destroy and uwinfo destroy). */
  139. SLIST_INIT(&info->codes);
  140. /* Number of codes = (Last code - end of info) >> 1 */
  141. if (!codebc) {
  142. yasm_value_initialize(&info->codes_count,
  143. yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(0)),
  144. line),
  145. 8);
  146. } else {
  147. yasm_value_initialize(&info->codes_count,
  148. yasm_expr_create(YASM_EXPR_SHR, yasm_expr_expr(
  149. yasm_expr_create(YASM_EXPR_SUB, yasm_expr_precbc(codebc),
  150. yasm_expr_precbc(infobc), line)),
  151. yasm_expr_int(yasm_intnum_create_uint(1)), line),
  152. 8);
  153. }
  154. /* 4-byte align */
  155. yasm_section_bcs_append(xdata, yasm_bc_create_align(
  156. yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(4)),
  157. line),
  158. NULL, NULL, NULL, line));
  159. /* Exception handler, if present. Use data bytecode. */
  160. if (info->ehandler) {
  161. yasm_datavalhead dvs;
  162. yasm_dvs_initialize(&dvs);
  163. yasm_dvs_append(&dvs, yasm_dv_create_expr(
  164. yasm_expr_create_ident(yasm_expr_sym(info->ehandler), line)));
  165. yasm_section_bcs_append(xdata,
  166. yasm_bc_create_data(&dvs, 4, 0, NULL, line));
  167. }
  168. }
  169. static void
  170. win64_uwinfo_bc_destroy(void *contents)
  171. {
  172. yasm_win64__uwinfo_destroy((coff_unwind_info *)contents);
  173. }
  174. static void
  175. win64_uwinfo_bc_print(const void *contents, FILE *f, int indent_level)
  176. {
  177. /* TODO */
  178. }
  179. static void
  180. win64_uwinfo_bc_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
  181. {
  182. coff_unwind_info *info = (coff_unwind_info *)bc->contents;
  183. if (yasm_value_finalize(&info->prolog_size, prev_bc))
  184. yasm_internal_error(N_("prolog size expression too complex"));
  185. if (yasm_value_finalize(&info->codes_count, prev_bc))
  186. yasm_internal_error(N_("codes count expression too complex"));
  187. if (yasm_value_finalize(&info->frameoff, prev_bc))
  188. yasm_error_set(YASM_ERROR_VALUE,
  189. N_("frame offset expression too complex"));
  190. }
  191. static int
  192. win64_uwinfo_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
  193. void *add_span_data)
  194. {
  195. coff_unwind_info *info = (coff_unwind_info *)bc->contents;
  196. /*@only@*/ /*@null@*/ yasm_intnum *intn;
  197. long intv;
  198. /* Want to make sure prolog size and codes count doesn't exceed
  199. * byte-size, and scaled frame offset doesn't exceed 4 bits.
  200. */
  201. add_span(add_span_data, bc, 1, &info->prolog_size, 0, 255);
  202. add_span(add_span_data, bc, 2, &info->codes_count, 0, 255);
  203. intn = yasm_value_get_intnum(&info->frameoff, bc, 0);
  204. if (intn) {
  205. intv = yasm_intnum_get_int(intn);
  206. if (intv < 0 || intv > 240)
  207. yasm_error_set(YASM_ERROR_VALUE,
  208. N_("frame offset of %ld bytes, must be between 0 and 240"),
  209. intv);
  210. else if ((intv & 0xF) != 0)
  211. yasm_error_set(YASM_ERROR_VALUE,
  212. N_("frame offset of %ld is not a multiple of 16"), intv);
  213. yasm_intnum_destroy(intn);
  214. } else
  215. add_span(add_span_data, bc, 3, &info->frameoff, 0, 240);
  216. bc->len += 4;
  217. return 0;
  218. }
  219. static int
  220. win64_uwinfo_bc_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
  221. /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
  222. {
  223. coff_unwind_info *info = (coff_unwind_info *)bc->contents;
  224. switch (span) {
  225. case 1:
  226. yasm_error_set_xref(yasm_symrec_get_def_line(info->prolog),
  227. N_("prologue ended here"));
  228. yasm_error_set(YASM_ERROR_VALUE,
  229. N_("prologue %ld bytes, must be <256"), new_val);
  230. return -1;
  231. case 2:
  232. yasm_error_set(YASM_ERROR_VALUE,
  233. N_("%ld unwind codes, maximum of 255"), new_val);
  234. return -1;
  235. case 3:
  236. yasm_error_set(YASM_ERROR_VALUE,
  237. N_("frame offset of %ld bytes, must be between 0 and 240"),
  238. new_val);
  239. return -1;
  240. default:
  241. yasm_internal_error(N_("unrecognized span id"));
  242. }
  243. return 0;
  244. }
  245. static int
  246. win64_uwinfo_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
  247. unsigned char *bufstart, void *d,
  248. yasm_output_value_func output_value,
  249. yasm_output_reloc_func output_reloc)
  250. {
  251. coff_unwind_info *info = (coff_unwind_info *)bc->contents;
  252. unsigned char *buf = *bufp;
  253. /*@only@*/ /*@null@*/ yasm_intnum *frameoff;
  254. long intv;
  255. /* Version and flags */
  256. if (info->ehandler)
  257. YASM_WRITE_8(buf, 1 | (UNW_FLAG_EHANDLER << 3));
  258. else
  259. YASM_WRITE_8(buf, 1);
  260. /* Size of prolog */
  261. output_value(&info->prolog_size, buf, 1, (unsigned long)(buf-bufstart),
  262. bc, 1, d);
  263. buf += 1;
  264. /* Count of codes */
  265. output_value(&info->codes_count, buf, 1, (unsigned long)(buf-bufstart),
  266. bc, 1, d);
  267. buf += 1;
  268. /* Frame register and offset */
  269. frameoff = yasm_value_get_intnum(&info->frameoff, bc, 1);
  270. if (!frameoff) {
  271. yasm_error_set(YASM_ERROR_VALUE,
  272. N_("frame offset expression too complex"));
  273. return 1;
  274. }
  275. intv = yasm_intnum_get_int(frameoff);
  276. if (intv < 0 || intv > 240)
  277. yasm_error_set(YASM_ERROR_VALUE,
  278. N_("frame offset of %ld bytes, must be between 0 and 240"), intv);
  279. else if ((intv & 0xF) != 0)
  280. yasm_error_set(YASM_ERROR_VALUE,
  281. N_("frame offset of %ld is not a multiple of 16"), intv);
  282. YASM_WRITE_8(buf, ((unsigned long)intv & 0xF0) | (info->framereg & 0x0F));
  283. yasm_intnum_destroy(frameoff);
  284. *bufp = buf;
  285. return 0;
  286. }
  287. static void
  288. win64_uwcode_bc_destroy(void *contents)
  289. {
  290. coff_unwind_code *code = (coff_unwind_code *)contents;
  291. yasm_value_delete(&code->off);
  292. yasm_xfree(contents);
  293. }
  294. static void
  295. win64_uwcode_bc_print(const void *contents, FILE *f, int indent_level)
  296. {
  297. /* TODO */
  298. }
  299. static void
  300. win64_uwcode_bc_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
  301. {
  302. coff_unwind_code *code = (coff_unwind_code *)bc->contents;
  303. if (yasm_value_finalize(&code->off, prev_bc))
  304. yasm_error_set(YASM_ERROR_VALUE, N_("offset expression too complex"));
  305. }
  306. static int
  307. win64_uwcode_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
  308. void *add_span_data)
  309. {
  310. coff_unwind_code *code = (coff_unwind_code *)bc->contents;
  311. int span = 0;
  312. /*@only@*/ /*@null@*/ yasm_intnum *intn;
  313. long intv;
  314. long low, high, mask;
  315. bc->len += 2; /* Prolog offset, code, and info */
  316. switch (code->opcode) {
  317. case UWOP_PUSH_NONVOL:
  318. case UWOP_SET_FPREG:
  319. case UWOP_PUSH_MACHFRAME:
  320. /* always 1 node */
  321. return 0;
  322. case UWOP_ALLOC_SMALL:
  323. case UWOP_ALLOC_LARGE:
  324. /* Start with smallest, then work our way up as necessary */
  325. code->opcode = UWOP_ALLOC_SMALL;
  326. code->info = 0;
  327. span = 1; low = 8; high = 128; mask = 0x7;
  328. break;
  329. case UWOP_SAVE_NONVOL:
  330. case UWOP_SAVE_NONVOL_FAR:
  331. /* Start with smallest, then work our way up as necessary */
  332. code->opcode = UWOP_SAVE_NONVOL;
  333. bc->len += 2; /* Scaled offset */
  334. span = 2;
  335. low = 0;
  336. high = 8*64*1024-8; /* 16-bit field, *8 scaling */
  337. mask = 0x7;
  338. break;
  339. case UWOP_SAVE_XMM128:
  340. case UWOP_SAVE_XMM128_FAR:
  341. /* Start with smallest, then work our way up as necessary */
  342. code->opcode = UWOP_SAVE_XMM128;
  343. bc->len += 2; /* Scaled offset */
  344. span = 3;
  345. low = 0;
  346. high = 16*64*1024-16; /* 16-bit field, *16 scaling */
  347. mask = 0xF;
  348. break;
  349. default:
  350. yasm_internal_error(N_("unrecognied unwind opcode"));
  351. /*@unreached@*/
  352. return 0;
  353. }
  354. intn = yasm_value_get_intnum(&code->off, bc, 0);
  355. if (intn) {
  356. intv = yasm_intnum_get_int(intn);
  357. if (intv > high) {
  358. /* Expand it ourselves here if we can and we're already larger */
  359. if (win64_uwcode_bc_expand(bc, span, intv, intv, &low, &high) > 0)
  360. add_span(add_span_data, bc, span, &code->off, low, high);
  361. }
  362. if (intv < low)
  363. yasm_error_set(YASM_ERROR_VALUE,
  364. N_("negative offset not allowed"));
  365. if ((intv & mask) != 0)
  366. yasm_error_set(YASM_ERROR_VALUE,
  367. N_("offset of %ld is not a multiple of %ld"), intv, mask+1);
  368. yasm_intnum_destroy(intn);
  369. } else
  370. add_span(add_span_data, bc, span, &code->off, low, high);
  371. return 0;
  372. }
  373. static int
  374. win64_uwcode_bc_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
  375. /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
  376. {
  377. coff_unwind_code *code = (coff_unwind_code *)bc->contents;
  378. if (new_val < 0) {
  379. yasm_error_set(YASM_ERROR_VALUE, N_("negative offset not allowed"));
  380. return -1;
  381. }
  382. if (span == 1) {
  383. /* 3 stages: SMALL, LARGE and info=0, LARGE and info=1 */
  384. if (code->opcode == UWOP_ALLOC_LARGE && code->info == 1)
  385. yasm_internal_error(N_("expansion on already largest alloc"));
  386. if (code->opcode == UWOP_ALLOC_SMALL && new_val > 128) {
  387. /* Overflowed small size */
  388. code->opcode = UWOP_ALLOC_LARGE;
  389. bc->len += 2;
  390. }
  391. if (new_val <= 8*64*1024-8) {
  392. /* Still can grow one more size */
  393. *pos_thres = 8*64*1024-8;
  394. return 1;
  395. }
  396. /* We're into the largest size */
  397. code->info = 1;
  398. bc->len += 2;
  399. } else if (code->opcode == UWOP_SAVE_NONVOL && span == 2) {
  400. code->opcode = UWOP_SAVE_NONVOL_FAR;
  401. bc->len += 2;
  402. } else if (code->opcode == UWOP_SAVE_XMM128 && span == 3) {
  403. code->opcode = UWOP_SAVE_XMM128_FAR;
  404. bc->len += 2;
  405. }
  406. return 0;
  407. }
  408. static int
  409. win64_uwcode_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
  410. unsigned char *bufstart, void *d,
  411. yasm_output_value_func output_value,
  412. yasm_output_reloc_func output_reloc)
  413. {
  414. coff_unwind_code *code = (coff_unwind_code *)bc->contents;
  415. unsigned char *buf = *bufp;
  416. yasm_value val;
  417. unsigned int size;
  418. int shift;
  419. long intv, low, high, mask;
  420. yasm_intnum *intn;
  421. /* Offset in prolog */
  422. yasm_value_initialize(&val,
  423. yasm_expr_create(YASM_EXPR_SUB, yasm_expr_sym(code->loc),
  424. yasm_expr_sym(code->proc), bc->line),
  425. 8);
  426. output_value(&val, buf, 1, (unsigned long)(buf-bufstart), bc, 1, d);
  427. buf += 1;
  428. yasm_value_delete(&val);
  429. /* Offset value */
  430. switch (code->opcode) {
  431. case UWOP_PUSH_NONVOL:
  432. case UWOP_SET_FPREG:
  433. case UWOP_PUSH_MACHFRAME:
  434. /* just 1 node, no offset; write opcode and info and we're done */
  435. YASM_WRITE_8(buf, (code->info << 4) | (code->opcode & 0xF));
  436. *bufp = buf;
  437. return 0;
  438. case UWOP_ALLOC_SMALL:
  439. /* 1 node, but offset stored in info */
  440. size = 0; low = 8; high = 128; shift = 3; mask = 0x7;
  441. break;
  442. case UWOP_ALLOC_LARGE:
  443. if (code->info == 0) {
  444. size = 2; low = 136; high = 8*64*1024-8; shift = 3;
  445. } else {
  446. size = 4; low = high = 0; shift = 0;
  447. }
  448. mask = 0x7;
  449. break;
  450. case UWOP_SAVE_NONVOL:
  451. size = 2; low = 0; high = 8*64*1024-8; shift = 3; mask = 0x7;
  452. break;
  453. case UWOP_SAVE_XMM128:
  454. size = 2; low = 0; high = 16*64*1024-16; shift = 4; mask = 0xF;
  455. break;
  456. case UWOP_SAVE_NONVOL_FAR:
  457. size = 4; low = high = 0; shift = 0; mask = 0x7;
  458. break;
  459. case UWOP_SAVE_XMM128_FAR:
  460. size = 4; low = high = 0; shift = 0; mask = 0xF;
  461. break;
  462. default:
  463. yasm_internal_error(N_("unrecognied unwind opcode"));
  464. /*@unreached@*/
  465. return 1;
  466. }
  467. /* Check for overflow */
  468. intn = yasm_value_get_intnum(&code->off, bc, 1);
  469. if (!intn) {
  470. yasm_error_set(YASM_ERROR_VALUE, N_("offset expression too complex"));
  471. return 1;
  472. }
  473. intv = yasm_intnum_get_int(intn);
  474. if (size != 4 && (intv < low || intv > high)) {
  475. yasm_error_set(YASM_ERROR_VALUE,
  476. N_("offset of %ld bytes, must be between %ld and %ld"),
  477. intv, low, high);
  478. return 1;
  479. }
  480. if ((intv & mask) != 0) {
  481. yasm_error_set(YASM_ERROR_VALUE,
  482. N_("offset of %ld is not a multiple of %ld"),
  483. intv, mask+1);
  484. return 1;
  485. }
  486. /* Stored value in info instead of extra code space */
  487. if (size == 0)
  488. code->info = (yasm_intnum_get_uint(intn) >> shift)-1;
  489. /* Opcode and info */
  490. YASM_WRITE_8(buf, (code->info << 4) | (code->opcode & 0xF));
  491. if (size != 0) {
  492. yasm_intnum_get_sized(intn, buf, size, size*8, -shift, 0, 1);
  493. buf += size;
  494. }
  495. yasm_intnum_destroy(intn);
  496. *bufp = buf;
  497. return 0;
  498. }