123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- /*
- * LC-3b bytecode utility functions
- *
- * Copyright (C) 2003-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
- #include <util.h>
- #include <libyasm.h>
- #include "lc3barch.h"
- /* Bytecode callback function prototypes */
- static void lc3b_bc_insn_destroy(void *contents);
- static void lc3b_bc_insn_print(const void *contents, FILE *f,
- int indent_level);
- static int lc3b_bc_insn_calc_len(yasm_bytecode *bc,
- yasm_bc_add_span_func add_span,
- void *add_span_data);
- static int lc3b_bc_insn_expand(yasm_bytecode *bc, int span, long old_val,
- long new_val, /*@out@*/ long *neg_thres,
- /*@out@*/ long *pos_thres);
- static int lc3b_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp,
- unsigned char *bufstart,
- void *d, yasm_output_value_func output_value,
- /*@null@*/ yasm_output_reloc_func output_reloc);
- /* Bytecode callback structures */
- static const yasm_bytecode_callback lc3b_bc_callback_insn = {
- lc3b_bc_insn_destroy,
- lc3b_bc_insn_print,
- yasm_bc_finalize_common,
- NULL,
- lc3b_bc_insn_calc_len,
- lc3b_bc_insn_expand,
- lc3b_bc_insn_tobytes,
- 0
- };
- void
- yasm_lc3b__bc_transform_insn(yasm_bytecode *bc, lc3b_insn *insn)
- {
- yasm_bc_transform(bc, &lc3b_bc_callback_insn, insn);
- }
- static void
- lc3b_bc_insn_destroy(void *contents)
- {
- lc3b_insn *insn = (lc3b_insn *)contents;
- yasm_value_delete(&insn->imm);
- yasm_xfree(contents);
- }
- static void
- lc3b_bc_insn_print(const void *contents, FILE *f, int indent_level)
- {
- const lc3b_insn *insn = (const lc3b_insn *)contents;
- fprintf(f, "%*s_Instruction_\n", indent_level, "");
- fprintf(f, "%*sImmediate Value:", indent_level, "");
- if (!insn->imm.abs)
- fprintf(f, " (nil)\n");
- else {
- indent_level++;
- fprintf(f, "\n");
- yasm_value_print(&insn->imm, f, indent_level);
- fprintf(f, "%*sType=", indent_level, "");
- switch (insn->imm_type) {
- case LC3B_IMM_NONE:
- fprintf(f, "NONE-SHOULDN'T HAPPEN");
- break;
- case LC3B_IMM_4:
- fprintf(f, "4-bit");
- break;
- case LC3B_IMM_5:
- fprintf(f, "5-bit");
- break;
- case LC3B_IMM_6_WORD:
- fprintf(f, "6-bit, word-multiple");
- break;
- case LC3B_IMM_6_BYTE:
- fprintf(f, "6-bit, byte-multiple");
- break;
- case LC3B_IMM_8:
- fprintf(f, "8-bit, word-multiple");
- break;
- case LC3B_IMM_9:
- fprintf(f, "9-bit, signed, word-multiple");
- break;
- case LC3B_IMM_9_PC:
- fprintf(f, "9-bit, signed, word-multiple, PC-relative");
- break;
- }
- indent_level--;
- }
- /* FIXME
- fprintf(f, "\n%*sOrigin=", indent_level, "");
- if (insn->origin) {
- fprintf(f, "\n");
- yasm_symrec_print(insn->origin, f, indent_level+1);
- } else
- fprintf(f, "(nil)\n");
- */
- fprintf(f, "%*sOpcode: %04x\n", indent_level, "",
- (unsigned int)insn->opcode);
- }
- static int
- lc3b_bc_insn_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
- void *add_span_data)
- {
- lc3b_insn *insn = (lc3b_insn *)bc->contents;
- yasm_bytecode *target_prevbc;
- /* Fixed size instruction length */
- bc->len += 2;
- /* Only need to worry about out-of-range to PC-relative */
- if (insn->imm_type != LC3B_IMM_9_PC)
- return 0;
- if (insn->imm.rel
- && (!yasm_symrec_get_label(insn->imm.rel, &target_prevbc)
- || target_prevbc->section != bc->section)) {
- /* External or out of segment, so we can't check distance. */
- return 0;
- }
- /* 9-bit signed, word-multiple displacement */
- add_span(add_span_data, bc, 1, &insn->imm, -512+(long)bc->len,
- 511+(long)bc->len);
- return 0;
- }
- static int
- lc3b_bc_insn_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
- /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
- {
- yasm_error_set(YASM_ERROR_VALUE, N_("jump target out of range"));
- return -1;
- }
- static int
- lc3b_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp,
- unsigned char *bufstart, void *d,
- yasm_output_value_func output_value,
- /*@unused@*/ yasm_output_reloc_func output_reloc)
- {
- lc3b_insn *insn = (lc3b_insn *)bc->contents;
- /*@only@*/ yasm_intnum *delta;
- unsigned long buf_off = (unsigned long)(*bufp - bufstart);
- /* Output opcode */
- YASM_SAVE_16_L(*bufp, insn->opcode);
- /* Insert immediate into opcode. */
- switch (insn->imm_type) {
- case LC3B_IMM_NONE:
- break;
- case LC3B_IMM_4:
- insn->imm.size = 4;
- if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
- return 1;
- break;
- case LC3B_IMM_5:
- insn->imm.size = 5;
- insn->imm.sign = 1;
- if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
- return 1;
- break;
- case LC3B_IMM_6_WORD:
- insn->imm.size = 6;
- if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
- return 1;
- break;
- case LC3B_IMM_6_BYTE:
- insn->imm.size = 6;
- insn->imm.sign = 1;
- if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
- return 1;
- break;
- case LC3B_IMM_8:
- insn->imm.size = 8;
- if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
- return 1;
- break;
- case LC3B_IMM_9_PC:
- /* Adjust relative displacement to end of bytecode */
- delta = yasm_intnum_create_int(-1);
- if (!insn->imm.abs)
- insn->imm.abs = yasm_expr_create_ident(yasm_expr_int(delta),
- bc->line);
- else
- insn->imm.abs =
- yasm_expr_create(YASM_EXPR_ADD,
- yasm_expr_expr(insn->imm.abs),
- yasm_expr_int(delta), bc->line);
- insn->imm.size = 9;
- insn->imm.sign = 1;
- if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
- return 1;
- break;
- case LC3B_IMM_9:
- insn->imm.size = 9;
- if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
- return 1;
- break;
- default:
- yasm_internal_error(N_("Unrecognized immediate type"));
- }
- *bufp += 2; /* all instructions are 2 bytes in size */
- return 0;
- }
- int
- yasm_lc3b__intnum_tobytes(yasm_arch *arch, const yasm_intnum *intn,
- unsigned char *buf, size_t destsize, size_t valsize,
- int shift, const yasm_bytecode *bc, int warn)
- {
- /* Write value out. */
- yasm_intnum_get_sized(intn, buf, destsize, valsize, shift, 0, warn);
- return 0;
- }
|