lc3bbc.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*
  2. * LC-3b bytecode utility functions
  3. *
  4. * Copyright (C) 2003-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 "lc3barch.h"
  30. /* Bytecode callback function prototypes */
  31. static void lc3b_bc_insn_destroy(void *contents);
  32. static void lc3b_bc_insn_print(const void *contents, FILE *f,
  33. int indent_level);
  34. static int lc3b_bc_insn_calc_len(yasm_bytecode *bc,
  35. yasm_bc_add_span_func add_span,
  36. void *add_span_data);
  37. static int lc3b_bc_insn_expand(yasm_bytecode *bc, int span, long old_val,
  38. long new_val, /*@out@*/ long *neg_thres,
  39. /*@out@*/ long *pos_thres);
  40. static int lc3b_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp,
  41. unsigned char *bufstart,
  42. void *d, yasm_output_value_func output_value,
  43. /*@null@*/ yasm_output_reloc_func output_reloc);
  44. /* Bytecode callback structures */
  45. static const yasm_bytecode_callback lc3b_bc_callback_insn = {
  46. lc3b_bc_insn_destroy,
  47. lc3b_bc_insn_print,
  48. yasm_bc_finalize_common,
  49. NULL,
  50. lc3b_bc_insn_calc_len,
  51. lc3b_bc_insn_expand,
  52. lc3b_bc_insn_tobytes,
  53. 0
  54. };
  55. void
  56. yasm_lc3b__bc_transform_insn(yasm_bytecode *bc, lc3b_insn *insn)
  57. {
  58. yasm_bc_transform(bc, &lc3b_bc_callback_insn, insn);
  59. }
  60. static void
  61. lc3b_bc_insn_destroy(void *contents)
  62. {
  63. lc3b_insn *insn = (lc3b_insn *)contents;
  64. yasm_value_delete(&insn->imm);
  65. yasm_xfree(contents);
  66. }
  67. static void
  68. lc3b_bc_insn_print(const void *contents, FILE *f, int indent_level)
  69. {
  70. const lc3b_insn *insn = (const lc3b_insn *)contents;
  71. fprintf(f, "%*s_Instruction_\n", indent_level, "");
  72. fprintf(f, "%*sImmediate Value:", indent_level, "");
  73. if (!insn->imm.abs)
  74. fprintf(f, " (nil)\n");
  75. else {
  76. indent_level++;
  77. fprintf(f, "\n");
  78. yasm_value_print(&insn->imm, f, indent_level);
  79. fprintf(f, "%*sType=", indent_level, "");
  80. switch (insn->imm_type) {
  81. case LC3B_IMM_NONE:
  82. fprintf(f, "NONE-SHOULDN'T HAPPEN");
  83. break;
  84. case LC3B_IMM_4:
  85. fprintf(f, "4-bit");
  86. break;
  87. case LC3B_IMM_5:
  88. fprintf(f, "5-bit");
  89. break;
  90. case LC3B_IMM_6_WORD:
  91. fprintf(f, "6-bit, word-multiple");
  92. break;
  93. case LC3B_IMM_6_BYTE:
  94. fprintf(f, "6-bit, byte-multiple");
  95. break;
  96. case LC3B_IMM_8:
  97. fprintf(f, "8-bit, word-multiple");
  98. break;
  99. case LC3B_IMM_9:
  100. fprintf(f, "9-bit, signed, word-multiple");
  101. break;
  102. case LC3B_IMM_9_PC:
  103. fprintf(f, "9-bit, signed, word-multiple, PC-relative");
  104. break;
  105. }
  106. indent_level--;
  107. }
  108. /* FIXME
  109. fprintf(f, "\n%*sOrigin=", indent_level, "");
  110. if (insn->origin) {
  111. fprintf(f, "\n");
  112. yasm_symrec_print(insn->origin, f, indent_level+1);
  113. } else
  114. fprintf(f, "(nil)\n");
  115. */
  116. fprintf(f, "%*sOpcode: %04x\n", indent_level, "",
  117. (unsigned int)insn->opcode);
  118. }
  119. static int
  120. lc3b_bc_insn_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
  121. void *add_span_data)
  122. {
  123. lc3b_insn *insn = (lc3b_insn *)bc->contents;
  124. yasm_bytecode *target_prevbc;
  125. /* Fixed size instruction length */
  126. bc->len += 2;
  127. /* Only need to worry about out-of-range to PC-relative */
  128. if (insn->imm_type != LC3B_IMM_9_PC)
  129. return 0;
  130. if (insn->imm.rel
  131. && (!yasm_symrec_get_label(insn->imm.rel, &target_prevbc)
  132. || target_prevbc->section != bc->section)) {
  133. /* External or out of segment, so we can't check distance. */
  134. return 0;
  135. }
  136. /* 9-bit signed, word-multiple displacement */
  137. add_span(add_span_data, bc, 1, &insn->imm, -512+(long)bc->len,
  138. 511+(long)bc->len);
  139. return 0;
  140. }
  141. static int
  142. lc3b_bc_insn_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
  143. /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
  144. {
  145. yasm_error_set(YASM_ERROR_VALUE, N_("jump target out of range"));
  146. return -1;
  147. }
  148. static int
  149. lc3b_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp,
  150. unsigned char *bufstart, void *d,
  151. yasm_output_value_func output_value,
  152. /*@unused@*/ yasm_output_reloc_func output_reloc)
  153. {
  154. lc3b_insn *insn = (lc3b_insn *)bc->contents;
  155. /*@only@*/ yasm_intnum *delta;
  156. unsigned long buf_off = (unsigned long)(*bufp - bufstart);
  157. /* Output opcode */
  158. YASM_SAVE_16_L(*bufp, insn->opcode);
  159. /* Insert immediate into opcode. */
  160. switch (insn->imm_type) {
  161. case LC3B_IMM_NONE:
  162. break;
  163. case LC3B_IMM_4:
  164. insn->imm.size = 4;
  165. if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
  166. return 1;
  167. break;
  168. case LC3B_IMM_5:
  169. insn->imm.size = 5;
  170. insn->imm.sign = 1;
  171. if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
  172. return 1;
  173. break;
  174. case LC3B_IMM_6_WORD:
  175. insn->imm.size = 6;
  176. if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
  177. return 1;
  178. break;
  179. case LC3B_IMM_6_BYTE:
  180. insn->imm.size = 6;
  181. insn->imm.sign = 1;
  182. if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
  183. return 1;
  184. break;
  185. case LC3B_IMM_8:
  186. insn->imm.size = 8;
  187. if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
  188. return 1;
  189. break;
  190. case LC3B_IMM_9_PC:
  191. /* Adjust relative displacement to end of bytecode */
  192. delta = yasm_intnum_create_int(-1);
  193. if (!insn->imm.abs)
  194. insn->imm.abs = yasm_expr_create_ident(yasm_expr_int(delta),
  195. bc->line);
  196. else
  197. insn->imm.abs =
  198. yasm_expr_create(YASM_EXPR_ADD,
  199. yasm_expr_expr(insn->imm.abs),
  200. yasm_expr_int(delta), bc->line);
  201. insn->imm.size = 9;
  202. insn->imm.sign = 1;
  203. if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
  204. return 1;
  205. break;
  206. case LC3B_IMM_9:
  207. insn->imm.size = 9;
  208. if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
  209. return 1;
  210. break;
  211. default:
  212. yasm_internal_error(N_("Unrecognized immediate type"));
  213. }
  214. *bufp += 2; /* all instructions are 2 bytes in size */
  215. return 0;
  216. }
  217. int
  218. yasm_lc3b__intnum_tobytes(yasm_arch *arch, const yasm_intnum *intn,
  219. unsigned char *buf, size_t destsize, size_t valsize,
  220. int shift, const yasm_bytecode *bc, int warn)
  221. {
  222. /* Write value out. */
  223. yasm_intnum_get_sized(intn, buf, destsize, valsize, shift, 0, warn);
  224. return 0;
  225. }