/*@-compmempass@*/ yasm_expr * yasm_expr_create(yasm_expr_op op, yasm_expr__item *left, yasm_expr__item *right, unsigned long line) { yasm_expr *ptr, *sube; unsigned long z; ptr = yasm_xmalloc(sizeof(yasm_expr)); ptr->op = op; ptr->numterms = 0; ptr->terms[0].type = YASM_EXPR_NONE; ptr->terms[1].type = YASM_EXPR_NONE; if (left) { ptr->terms[0] = *left; /* structure copy */ z = (unsigned long)(left-itempool); if (z>=31) yasm_internal_error(N_("could not find expritem in pool")); itempool_used &= ~(1<<z); ptr->numterms++; /* Search downward until we find something *other* than an * IDENT, then bring it up to the current level. */ while (ptr->terms[0].type == YASM_EXPR_EXPR && ptr->terms[0].data.expn->op == YASM_EXPR_IDENT) { sube = ptr->terms[0].data.expn; ptr->terms[0] = sube->terms[0]; /* structure copy */ /*@-usereleased@*/ yasm_xfree(sube); /*@=usereleased@*/ } } else { yasm_internal_error(N_("Right side of expression must exist")); } if (right) { ptr->terms[1] = *right; /* structure copy */ z = (unsigned long)(right-itempool); if (z>=31) yasm_internal_error(N_("could not find expritem in pool")); itempool_used &= ~(1<<z); ptr->numterms++; /* Search downward until we find something *other* than an * IDENT, then bring it up to the current level. */ while (ptr->terms[1].type == YASM_EXPR_EXPR && ptr->terms[1].data.expn->op == YASM_EXPR_IDENT) { sube = ptr->terms[1].data.expn; ptr->terms[1] = sube->terms[0]; /* structure copy */ /*@-usereleased@*/ yasm_xfree(sube); /*@=usereleased@*/ } } ptr->line = line; return expr_level_op(ptr, 1, 1, 0); }
/* takes ownership of addr */ elf_reloc_entry * elf_reloc_entry_create(yasm_symrec *sym, yasm_symrec *wrt, yasm_intnum *addr, int rel, size_t valsize) { elf_reloc_entry *entry; if (!elf_march->accepts_reloc) yasm_internal_error(N_("Unsupported machine for ELF output")); if (!elf_march->accepts_reloc(valsize, wrt, elf_ssyms)) { if (addr) yasm_intnum_destroy(addr); return NULL; } if (sym == NULL) yasm_internal_error("sym is null"); entry = yasm_xmalloc(sizeof(elf_reloc_entry)); entry->reloc.sym = sym; entry->reloc.addr = addr; entry->rtype_rel = rel; entry->valsize = valsize; entry->addend = NULL; entry->wrt = wrt; return entry; }
long yasm_intnum_get_int(const yasm_intnum *intn) { switch (intn->type) { case INTNUM_L: return intn->val.l; case INTNUM_BV: if (BitVector_msb_(intn->val.bv)) { /* it's negative: negate the bitvector to get a positive * number, then negate the positive number. */ unsigned long ul; BitVector_Negate(conv_bv, intn->val.bv); if (Set_Max(conv_bv) >= 32) { /* too negative */ return LONG_MIN; } ul = BitVector_Chunk_Read(conv_bv, 32, 0); /* check for too negative */ return (ul & 0x80000000) ? LONG_MIN : -((long)ul); } /* it's positive, and since it's a BV, it must be >0x7FFFFFFF */ return LONG_MAX; default: yasm_internal_error(N_("unknown intnum type")); /*@notreached@*/ return 0; } }
yasm_intnum * yasm_intnum_create_sized(unsigned char *ptr, int sign, size_t srcsize, int bigendian) { yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum)); unsigned long i = 0; if (srcsize*8 > BITVECT_NATIVE_SIZE) yasm_error_set(YASM_ERROR_OVERFLOW, N_("Numeric constant too large for internal format")); /* Read the buffer into a bitvect */ BitVector_Empty(conv_bv); if (bigendian) { /* TODO */ yasm_internal_error(N_("big endian not implemented")); } else { for (i = 0; i < srcsize; i++) BitVector_Chunk_Store(conv_bv, 8, i*8, ptr[i]); } /* Sign extend if needed */ if (srcsize*8 < BITVECT_NATIVE_SIZE && sign && (ptr[i-1] & 0x80) == 0x80) BitVector_Interval_Fill(conv_bv, i*8, BITVECT_NATIVE_SIZE-1); intnum_frombv(intn, conv_bv); return intn; }
/*@null@*/ /*@only@*/ unsigned char * yasm_bc_tobytes(yasm_bytecode *bc, unsigned char *buf, unsigned long *bufsize, /*@out@*/ int *gap, void *d, yasm_output_value_func output_value, /*@null@*/ yasm_output_reloc_func output_reloc) /*@sets *buf@*/ { /*@only@*/ /*@null@*/ unsigned char *mybuf = NULL; unsigned char *origbuf, *destbuf; long i; int error = 0; if (yasm_bc_get_multiple(bc, &bc->mult_int, 1) || bc->mult_int == 0) { *bufsize = 0; return NULL; } /* special case for reserve bytecodes */ if (bc->callback->special == YASM_BC_SPECIAL_RESERVE) { *bufsize = bc->len*bc->mult_int; *gap = 1; return NULL; /* we didn't allocate a buffer */ } *gap = 0; if (*bufsize < bc->len*bc->mult_int) { mybuf = yasm_xmalloc(bc->len*bc->mult_int); destbuf = mybuf; } else destbuf = buf; *bufsize = bc->len*bc->mult_int; if (!bc->callback) yasm_internal_error(N_("got empty bytecode in bc_tobytes")); else for (i=0; i<bc->mult_int; i++) { origbuf = destbuf; error = bc->callback->tobytes(bc, &destbuf, d, output_value, output_reloc); if (!error && ((unsigned long)(destbuf - origbuf) != bc->len)) yasm_internal_error( N_("written length does not match optimized length")); } return mybuf; }
int yasm_bc_calc_len_common(yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data) { yasm_internal_error(N_("bytecode length cannot be calculated")); /*@unreached@*/ return 0; }
int yasm_bc_expand_common(yasm_bytecode *bc, int span, long old_val, long new_val, /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres) { yasm_internal_error(N_("bytecode does not have any dependent spans")); /*@unreached@*/ return 0; }
int yasm_bc_tobytes_common(yasm_bytecode *bc, unsigned char **bufp, void *d, yasm_output_value_func output_value, /*@null@*/ yasm_output_reloc_func output_reloc) { yasm_internal_error(N_("bytecode cannot be converted to bytes")); /*@unreached@*/ return 0; }
elf_strtab_entry * elf_strtab_append_str(elf_strtab_head *strtab, const char *str) { elf_strtab_entry *last, *entry; if (strtab == NULL) yasm_internal_error("strtab is null"); if (STAILQ_EMPTY(strtab)) yasm_internal_error("strtab is missing initial dummy entry"); last = STAILQ_LAST(strtab, elf_strtab_entry, qlink); entry = elf_strtab_entry_create(str); entry->index = last->index + (unsigned long)strlen(last->str) + 1; STAILQ_INSERT_TAIL(strtab, entry, qlink); return entry; }
static unsigned int elf_x86_amd64_map_reloc_info_to_type(elf_reloc_entry *reloc, yasm_symrec **ssyms) { if (reloc->wrt) { size_t i; for (i=0; i<NELEMS(elf_x86_amd64_ssyms); i++) { if (reloc->wrt == ssyms[i] && reloc->valsize == elf_x86_amd64_ssyms[i].size) { /* Force TLS type; this is required by the linker. */ if (elf_x86_amd64_ssyms[i].sym_rel & ELF_SSYM_THREAD_LOCAL) { elf_symtab_entry *esym; esym = yasm_symrec_get_data(reloc->reloc.sym, &elf_symrec_data); if (esym) esym->type = STT_TLS; } /* Map PC-relative GOT to appropriate relocation */ if (reloc->rtype_rel && elf_x86_amd64_ssyms[i].reloc == R_X86_64_GOT32) return (unsigned char) R_X86_64_GOTPCREL; return (unsigned char) elf_x86_amd64_ssyms[i].reloc; } } yasm_internal_error(N_("Unsupported WRT")); } else if (reloc->rtype_rel) { switch (reloc->valsize) { case 8: return (unsigned char) R_X86_64_PC8; case 16: return (unsigned char) R_X86_64_PC16; case 32: return (unsigned char) R_X86_64_PC32; default: yasm_internal_error(N_("Unsupported relocation size")); } } else { switch (reloc->valsize) { case 8: return (unsigned char) R_X86_64_8; case 16: return (unsigned char) R_X86_64_16; case 32: return (unsigned char) R_X86_64_32; case 64: return (unsigned char) R_X86_64_64; default: yasm_internal_error(N_("Unsupported relocation size")); } } return 0; }
static unsigned int elf_x86_amd64_map_reloc_info_to_type(elf_reloc_entry *reloc) { if (reloc->wrt) { const elf_machine_ssym *ssym = (elf_machine_ssym *) yasm_symrec_get_data(reloc->wrt, &elf_ssym_symrec_data); if (!ssym || reloc->valsize != ssym->size) yasm_internal_error(N_("Unsupported WRT")); /* Force TLS type; this is required by the linker. */ if (ssym->sym_rel & ELF_SSYM_THREAD_LOCAL) { elf_symtab_entry *esym; esym = yasm_symrec_get_data(reloc->reloc.sym, &elf_symrec_data); if (esym) esym->type = STT_TLS; } /* Map PC-relative GOT to appropriate relocation */ if (reloc->rtype_rel && ssym->reloc == R_X86_64_GOT32) return (unsigned char) R_X86_64_GOTPCREL; return (unsigned char) ssym->reloc; } else if (reloc->is_GOT_sym && reloc->valsize == 32) { return (unsigned char) R_X86_64_GOTPC32; } else if (reloc->is_GOT_sym && reloc->valsize == 64) { return (unsigned char) R_X86_64_GOTPC64; } else if (reloc->rtype_rel) { switch (reloc->valsize) { case 8: return (unsigned char) R_X86_64_PC8; case 16: return (unsigned char) R_X86_64_PC16; case 32: return (unsigned char) R_X86_64_PC32; case 64: return (unsigned char) R_X86_64_PC64; default: yasm_internal_error(N_("Unsupported relocation size")); } } else { switch (reloc->valsize) { case 8: return (unsigned char) R_X86_64_8; case 16: return (unsigned char) R_X86_64_16; case 32: return (unsigned char) R_X86_64_32; case 64: return (unsigned char) R_X86_64_64; default: yasm_internal_error(N_("Unsupported relocation size")); } } return 0; }
void elf_strtab_destroy(elf_strtab_head *strtab) { elf_strtab_entry *s1, *s2; if (strtab == NULL) yasm_internal_error("strtab is null"); if (STAILQ_EMPTY(strtab)) yasm_internal_error("strtab is missing initial dummy entry"); s1 = STAILQ_FIRST(strtab); while (s1 != NULL) { s2 = STAILQ_NEXT(s1, qlink); yasm_xfree(s1->str); yasm_xfree(s1); s1 = s2; } yasm_xfree(strtab); }
/* IEEE-754r "half precision" format: * 16 bits: * 15 9 Bit 0 * | | | * seee eemm mmmm mmmm * * e = bias 15 exponent * s = sign bit * m = mantissa bits, bit 10 is an implied one bit. * * IEEE-754 (Intel) "single precision" format: * 32 bits: * Bit 31 Bit 22 Bit 0 * | | | * seeeeeee emmmmmmm mmmmmmmm mmmmmmmm * * e = bias 127 exponent * s = sign bit * m = mantissa bits, bit 23 is an implied one bit. * * IEEE-754 (Intel) "double precision" format: * 64 bits: * bit 63 bit 51 bit 0 * | | | * seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm * * e = bias 1023 exponent. * s = sign bit. * m = mantissa bits. Bit 52 is an implied one bit. * * IEEE-754 (Intel) "extended precision" format: * 80 bits: * bit 79 bit 63 bit 0 * | | | * seeeeeee eeeeeeee mmmmmmmm m...m m...m m...m m...m m...m * * e = bias 16383 exponent * m = 64 bit mantissa with NO implied bit! * s = sign (for mantissa) */ int yasm_floatnum_get_sized(const yasm_floatnum *flt, unsigned char *ptr, size_t destsize, size_t valsize, size_t shift, int bigendian, int warn) { int retval; if (destsize*8 != valsize || shift>0 || bigendian) { /* TODO */ yasm_internal_error(N_("unsupported floatnum functionality")); } switch (destsize) { case 2: retval = floatnum_get_common(flt, ptr, 2, 10, 1, 5); break; case 4: retval = floatnum_get_common(flt, ptr, 4, 23, 1, 8); break; case 8: retval = floatnum_get_common(flt, ptr, 8, 52, 1, 11); break; case 10: retval = floatnum_get_common(flt, ptr, 10, 64, 0, 15); break; default: yasm_internal_error(N_("Invalid float conversion size")); /*@notreached@*/ return 1; } if (warn) { if (retval < 0) yasm_warn_set(YASM_WARN_GENERAL, N_("underflow in floating point expression")); else if (retval > 0) yasm_warn_set(YASM_WARN_GENERAL, N_("overflow in floating point expression")); } return retval; }
static int bc_incbin_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) { bytecode_incbin *incbin = (bytecode_incbin *)bc->contents; FILE *f; /*@dependent@*/ /*@null@*/ const yasm_intnum *num; unsigned long start = 0; /* Convert start to integer value */ if (incbin->start) { num = yasm_expr_get_intnum(&incbin->start, 0); if (!num) yasm_internal_error( N_("could not determine start in bc_tobytes_incbin")); start = yasm_intnum_get_uint(num); } /* Open file */ f = yasm_fopen_include(incbin->filename, incbin->from, "rb", NULL); if (!f) { yasm_error_set(YASM_ERROR_IO, N_("`incbin': unable to open file `%s'"), incbin->filename); return 1; } /* Seek to start of data */ if (fseek(f, (long)start, SEEK_SET) < 0) { yasm_error_set(YASM_ERROR_IO, N_("`incbin': unable to seek on file `%s'"), incbin->filename); fclose(f); return 1; } /* Read len bytes */ if (fread(*bufp, 1, (size_t)bc->len, f) < (size_t)bc->len) { yasm_error_set(YASM_ERROR_IO, N_("`incbin': unable to read %lu bytes from file `%s'"), bc->len, incbin->filename); fclose(f); return 1; } *bufp += bc->len; fclose(f); return 0; }
/* helpers */ static yasm_expr__item * expr_get_item(void) { int z = 0; unsigned long v = itempool_used & 0x7fffffff; while (v & 1) { v >>= 1; z++; } if (z>=31) yasm_internal_error(N_("too many expritems")); itempool_used |= 1<<z; return &itempool[z]; }
unsigned long elf_strtab_output_to_file(FILE *f, elf_strtab_head *strtab) { unsigned long size = 0; elf_strtab_entry *entry; if (strtab == NULL) yasm_internal_error("strtab is null"); /* consider optimizing tables here */ STAILQ_FOREACH(entry, strtab, qlink) { size_t len = 1 + strlen(entry->str); fwrite(entry->str, len, 1, f); size += (unsigned long)len; }
int yasm_bc_expand(yasm_bytecode *bc, int span, long old_val, long new_val, /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres) { if (span == 0) { bc->mult_int = new_val; return 1; } if (!bc->callback) { yasm_internal_error(N_("got empty bytecode in yasm_bc_expand")); /*@unreached@*/ return -1; } else return bc->callback->expand(bc, span, old_val, new_val, neg_thres, pos_thres); }
int yasm_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data) { int retval = 0; bc->len = 0; if (!bc->callback) yasm_internal_error(N_("got empty bytecode in yasm_bc_calc_len")); else retval = bc->callback->calc_len(bc, add_span, add_span_data); /* Check for multiples */ bc->mult_int = 1; if (bc->multiple) { /*@dependent@*/ /*@null@*/ const yasm_intnum *num; num = yasm_expr_get_intnum(&bc->multiple, 0); if (num) { if (yasm_intnum_sign(num) < 0) { yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative")); retval = -1; } else bc->mult_int = yasm_intnum_get_int(num); } else { if (yasm_expr__contains(bc->multiple, YASM_EXPR_FLOAT)) { yasm_error_set(YASM_ERROR_VALUE, N_("expression must not contain floating point value")); retval = -1; } else { yasm_value value; yasm_value_initialize(&value, bc->multiple, 0); add_span(add_span_data, bc, 0, &value, 0, 0); bc->mult_int = 0; /* assume 0 to start */ } } } /* If we got an error somewhere along the line, clear out any calc len */ if (retval < 0) bc->len = 0; return retval; }
unsigned long yasm_intnum_get_uint(const yasm_intnum *intn) { switch (intn->type) { case INTNUM_L: if (intn->val.l < 0) return 0; return (unsigned long)intn->val.l; case INTNUM_BV: if (BitVector_msb_(intn->val.bv)) return 0; if (Set_Max(intn->val.bv) > 32) return ULONG_MAX; return BitVector_Chunk_Read(intn->val.bv, 32, 0); default: yasm_internal_error(N_("unknown intnum type")); /*@notreached@*/ return 0; } }
static void elf_x86_amd64_write_symtab_entry(unsigned char *bufp, elf_symtab_entry *entry, yasm_intnum *value_intn, yasm_intnum *size_intn) { YASM_WRITE_32_L(bufp, entry->name ? entry->name->index : 0); YASM_WRITE_8(bufp, ELF64_ST_INFO(entry->bind, entry->type)); YASM_WRITE_8(bufp, ELF64_ST_OTHER(entry->vis)); if (entry->sect) { elf_secthead *shead = yasm_section_get_data(entry->sect, &elf_section_data); if (!shead) yasm_internal_error(N_("symbol references section without data")); YASM_WRITE_16_L(bufp, shead->index); } else { YASM_WRITE_16_L(bufp, entry->index); } YASM_WRITE_64I_L(bufp, value_intn); YASM_WRITE_64I_L(bufp, size_intn); }
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; }
static int xdf_objfmt_output_section(yasm_section *sect, /*@null@*/ void *d) { /*@null@*/ xdf_objfmt_output_info *info = (xdf_objfmt_output_info *)d; /*@dependent@*/ /*@null@*/ xdf_section_data *xsd; long pos; xdf_reloc *reloc; assert(info != NULL); xsd = yasm_section_get_data(sect, &xdf_section_data_cb); assert(xsd != NULL); if (xsd->flags & XDF_SECT_BSS) { /* Don't output BSS sections. * TODO: Check for non-reserve bytecodes? */ pos = 0; /* position = 0 because it's not in the file */ xsd->size = yasm_bc_next_offset(yasm_section_bcs_last(sect)); } else { pos = ftell(info->f); if (pos == -1) { yasm__fatal(N_("could not get file position on output file")); /*@notreached@*/ return 1; } info->sect = sect; info->xsd = xsd; yasm_section_bcs_traverse(sect, info->errwarns, info, xdf_objfmt_output_bytecode); /* Sanity check final section size */ if (xsd->size != yasm_bc_next_offset(yasm_section_bcs_last(sect))) yasm_internal_error( N_("xdf: section computed size did not match actual size")); } /* Empty? Go on to next section */ if (xsd->size == 0) return 0; xsd->scnptr = (unsigned long)pos; /* No relocations to output? Go on to next section */ if (xsd->nreloc == 0) return 0; pos = ftell(info->f); if (pos == -1) { yasm__fatal(N_("could not get file position on output file")); /*@notreached@*/ return 1; } xsd->relptr = (unsigned long)pos; reloc = (xdf_reloc *)yasm_section_relocs_first(sect); while (reloc) { unsigned char *localbuf = info->buf; /*@null@*/ xdf_symrec_data *xsymd; xsymd = yasm_symrec_get_data(reloc->reloc.sym, &xdf_symrec_data_cb); if (!xsymd) yasm_internal_error( N_("xdf: no symbol data for relocated symbol")); yasm_intnum_get_sized(reloc->reloc.addr, localbuf, 4, 32, 0, 0, 0); localbuf += 4; /* address of relocation */ YASM_WRITE_32_L(localbuf, xsymd->index); /* relocated symbol */ if (reloc->base) { xsymd = yasm_symrec_get_data(reloc->base, &xdf_symrec_data_cb); if (!xsymd) yasm_internal_error( N_("xdf: no symbol data for relocated base symbol")); YASM_WRITE_32_L(localbuf, xsymd->index); /* base symbol */ } else { if (reloc->type == XDF_RELOC_WRT) yasm_internal_error( N_("xdf: no base symbol for WRT relocation")); YASM_WRITE_32_L(localbuf, 0); /* no base symbol */ } YASM_WRITE_8(localbuf, reloc->type); /* type of relocation */ YASM_WRITE_8(localbuf, reloc->size); /* size of relocation */ YASM_WRITE_8(localbuf, reloc->shift); /* relocation shift */ YASM_WRITE_8(localbuf, 0); /* flags */ fwrite(info->buf, 16, 1, info->f); reloc = (xdf_reloc *)yasm_section_reloc_next((yasm_reloc *)reloc); } return 0; }
static int xdf_objfmt_output_sym(yasm_symrec *sym, /*@null@*/ void *d) { /*@null@*/ xdf_objfmt_output_info *info = (xdf_objfmt_output_info *)d; yasm_sym_vis vis = yasm_symrec_get_visibility(sym); assert(info != NULL); if (info->all_syms || vis != YASM_SYM_LOCAL) { /*@only@*/ char *name = yasm_symrec_get_global_name(sym, info->object); const yasm_expr *equ_val; const yasm_intnum *intn; size_t len = strlen(name); unsigned long value = 0; long scnum = -3; /* -3 = debugging symbol */ /*@dependent@*/ /*@null@*/ yasm_section *sect; /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc; unsigned long flags = 0; unsigned char *localbuf; if (vis & YASM_SYM_GLOBAL) flags = XDF_SYM_GLOBAL; /* Look at symrec for value/scnum/etc. */ if (yasm_symrec_get_label(sym, &precbc)) { if (precbc) sect = yasm_bc_get_section(precbc); else sect = NULL; /* it's a label: get value and offset. * If there is not a section, leave as debugging symbol. */ if (sect) { /*@dependent@*/ /*@null@*/ xdf_section_data *csectd; csectd = yasm_section_get_data(sect, &xdf_section_data_cb); if (csectd) scnum = csectd->scnum; else yasm_internal_error(N_("didn't understand section")); if (precbc) value += yasm_bc_next_offset(precbc); } } else if ((equ_val = yasm_symrec_get_equ(sym))) { yasm_expr *equ_val_copy = yasm_expr_copy(equ_val); intn = yasm_expr_get_intnum(&equ_val_copy, 1); if (!intn) { if (vis & YASM_SYM_GLOBAL) { yasm_error_set(YASM_ERROR_NOT_CONSTANT, N_("global EQU value not an integer expression")); yasm_errwarn_propagate(info->errwarns, equ_val->line); } } else value = yasm_intnum_get_uint(intn); yasm_expr_destroy(equ_val_copy); flags |= XDF_SYM_EQU; scnum = -2; /* -2 = absolute symbol */ } else { if (vis & YASM_SYM_EXTERN) { flags = XDF_SYM_EXTERN; scnum = -1; } } localbuf = info->buf; YASM_WRITE_32_L(localbuf, scnum); /* section number */ YASM_WRITE_32_L(localbuf, value); /* value */ YASM_WRITE_32_L(localbuf, info->strtab_offset); info->strtab_offset += (unsigned long)(len+1); YASM_WRITE_32_L(localbuf, flags); /* flags */ fwrite(info->buf, 16, 1, info->f); yasm_xfree(name); } return 0; }
int yasm_value_finalize(yasm_value *value, yasm_bytecode *precbc) { if (!value->abs) return 0; value->abs = yasm_expr__level_tree(value->abs, 1, 1, 0, 0, NULL, NULL); /* quit early if there was an issue in simplify() */ if (yasm_error_occurred()) return 1; /* Strip top-level AND masking to an all-1s mask the same size * of the value size. This allows forced avoidance of overflow warnings. */ if (value->abs->op == YASM_EXPR_AND) { int term; /* Calculate 1<<size - 1 value */ yasm_intnum *mask = yasm_intnum_create_uint(1); yasm_intnum *mask_tmp = yasm_intnum_create_uint(value->size); yasm_intnum_calc(mask, YASM_EXPR_SHL, mask_tmp); yasm_intnum_set_uint(mask_tmp, 1); yasm_intnum_calc(mask, YASM_EXPR_SUB, mask_tmp); yasm_intnum_destroy(mask_tmp); /* Walk terms and delete matching masks */ for (term=value->abs->numterms-1; term>=0; term--) { if (value->abs->terms[term].type == YASM_EXPR_INT && yasm_intnum_compare(value->abs->terms[term].data.intn, mask) == 0) { /* Delete the intnum */ yasm_intnum_destroy(value->abs->terms[term].data.intn); /* Slide everything to its right over by 1 */ if (term != value->abs->numterms-1) /* if it wasn't last.. */ memmove(&value->abs->terms[term], &value->abs->terms[term+1], (value->abs->numterms-1-term)* sizeof(yasm_expr__item)); /* Update numterms */ value->abs->numterms--; /* Indicate warnings have been disabled */ value->no_warn = 1; } } if (value->abs->numterms == 1) value->abs->op = YASM_EXPR_IDENT; yasm_intnum_destroy(mask); } /* Handle trivial (IDENT) cases immediately */ if (value->abs->op == YASM_EXPR_IDENT) { switch (value->abs->terms[0].type) { case YASM_EXPR_INT: if (yasm_intnum_is_zero(value->abs->terms[0].data.intn)) { yasm_expr_destroy(value->abs); value->abs = NULL; } return 0; case YASM_EXPR_REG: case YASM_EXPR_FLOAT: return 0; case YASM_EXPR_SYM: value->rel = value->abs->terms[0].data.sym; yasm_expr_destroy(value->abs); value->abs = NULL; return 0; case YASM_EXPR_EXPR: /* Bring up lower values. */ while (value->abs->op == YASM_EXPR_IDENT && value->abs->terms[0].type == YASM_EXPR_EXPR) { yasm_expr *sube = value->abs->terms[0].data.expn; yasm_xfree(value->abs); value->abs = sube; } break; default: yasm_internal_error(N_("unexpected expr term type")); } } if (value_finalize_scan(value, value->abs, precbc, 0)) return 1; value->abs = yasm_expr__level_tree(value->abs, 1, 1, 0, 0, NULL, NULL); /* Simplify 0 in abs to NULL */ if (value->abs->op == YASM_EXPR_IDENT && value->abs->terms[0].type == YASM_EXPR_INT && yasm_intnum_is_zero(value->abs->terms[0].data.intn)) { yasm_expr_destroy(value->abs); value->abs = NULL; } return 0; }
/* Function used by conversion routines to actually perform the conversion. * * ptr -> the array to return the little-endian floating point value into. * flt -> the floating point value to convert. * byte_size -> the size in bytes of the output format. * mant_bits -> the size in bits of the output mantissa. * implicit1 -> does the output format have an implicit 1? 1=yes, 0=no. * exp_bits -> the size in bits of the output exponent. * * Returns 0 on success, 1 if overflow, -1 if underflow. */ static int floatnum_get_common(const yasm_floatnum *flt, /*@out@*/ unsigned char *ptr, N_int byte_size, N_int mant_bits, int implicit1, N_int exp_bits) { long exponent = (long)flt->exponent; wordptr output; charptr buf; unsigned int len; unsigned int overflow = 0, underflow = 0; int retval = 0; long exp_bias = (1<<(exp_bits-1))-1; long exp_inf = (1<<exp_bits)-1; output = BitVector_Create(byte_size*8, TRUE); /* copy mantissa */ BitVector_Interval_Copy(output, flt->mantissa, 0, (N_int)((MANT_BITS-implicit1)-mant_bits), mant_bits); /* round mantissa */ if (BitVector_bit_test(flt->mantissa, (MANT_BITS-implicit1)-(mant_bits+1))) BitVector_increment(output); if (BitVector_bit_test(output, mant_bits)) { /* overflowed, so zero mantissa (and set explicit bit if necessary) */ BitVector_Empty(output); BitVector_Bit_Copy(output, mant_bits-1, !implicit1); /* and up the exponent (checking for overflow) */ if (exponent+1 >= EXP_INF) overflow = 1; else exponent++; } /* adjust the exponent to the output bias, checking for overflow */ exponent -= EXP_BIAS-exp_bias; if (exponent >= exp_inf) overflow = 1; else if (exponent <= 0) underflow = 1; /* underflow and overflow both set!? */ if (underflow && overflow) yasm_internal_error(N_("Both underflow and overflow set")); /* check for underflow or overflow and set up appropriate output */ if (underflow) { BitVector_Empty(output); exponent = 0; if (!(flt->flags & FLAG_ISZERO)) retval = -1; } else if (overflow) { BitVector_Empty(output); exponent = exp_inf; retval = 1; } /* move exponent into place */ BitVector_Chunk_Store(output, exp_bits, mant_bits, (N_long)exponent); /* merge in sign bit */ BitVector_Bit_Copy(output, byte_size*8-1, flt->sign); /* get little-endian bytes */ buf = BitVector_Block_Read(output, &len); if (len < byte_size) yasm_internal_error( N_("Byte length of BitVector does not match bit length")); /* copy to output */ memcpy(ptr, buf, byte_size*sizeof(unsigned char)); /* free allocated resources */ yasm_xfree(buf); BitVector_Destroy(output); return retval; }
void yasm_intnum_get_sized(const yasm_intnum *intn, unsigned char *ptr, size_t destsize, size_t valsize, int shift, int bigendian, int warn) { wordptr op1 = op1static, op2; unsigned char *buf; unsigned int len; size_t rshift = shift < 0 ? (size_t)(-shift) : 0; int carry_in; /* Currently don't support destinations larger than our native size */ if (destsize*8 > BITVECT_NATIVE_SIZE) yasm_internal_error(N_("destination too large")); /* General size warnings */ if (warn<0 && !yasm_intnum_check_size(intn, valsize, rshift, 1)) yasm_warn_set(YASM_WARN_GENERAL, N_("value does not fit in signed %d bit field"), valsize); if (warn>0 && !yasm_intnum_check_size(intn, valsize, rshift, 2)) yasm_warn_set(YASM_WARN_GENERAL, N_("value does not fit in %d bit field"), valsize); /* Read the original data into a bitvect */ if (bigendian) { /* TODO */ yasm_internal_error(N_("big endian not implemented")); } else BitVector_Block_Store(op1, ptr, (N_int)destsize); /* If not already a bitvect, convert value to be written to a bitvect */ op2 = intnum_tobv(op2static, intn); /* Check low bits if right shifting and warnings enabled */ if (warn && rshift > 0) { BitVector_Copy(conv_bv, op2); BitVector_Move_Left(conv_bv, (N_int)(BITVECT_NATIVE_SIZE-rshift)); if (!BitVector_is_empty(conv_bv)) yasm_warn_set(YASM_WARN_GENERAL, N_("misaligned value, truncating to boundary")); } /* Shift right if needed */ if (rshift > 0) { carry_in = BitVector_msb_(op2); while (rshift-- > 0) BitVector_shift_right(op2, carry_in); shift = 0; } /* Write the new value into the destination bitvect */ BitVector_Interval_Copy(op1, op2, (unsigned int)shift, 0, (N_int)valsize); /* Write out the new data */ buf = BitVector_Block_Read(op1, &len); if (bigendian) { /* TODO */ yasm_internal_error(N_("big endian not implemented")); } else memcpy(ptr, buf, destsize); yasm_xfree(buf); }