output_expr_func output_expr);
} bc;
+ /* Functions to output floats and integers, architecture-specific because
+ * of endianness. Returns nonzero on error, otherwise updates bufp by
+ * valsize (bytes saved to bufp). For intnums, rel indicates a relative
+ * displacement, and bc is the containing bytecode to compute it from.
+ */
+ int (*floatnum_tobytes) (const floatnum *flt, unsigned char **bufp,
+ unsigned long valsize, const expr *e);
+ int (*intnum_tobytes) (const intnum *intn, unsigned char **bufp,
+ unsigned long valsize, const expr *e,
+ const bytecode *bc, int rel);
+
/* Gets the equivalent register size in bytes. Returns 0 if there is no
* suitable equivalent size.
*/
if (slen > 0) {
slen = bc_data->size-slen;
for (i=0; i<slen; i++)
- WRITE_BYTE(*bufp, 0);
+ WRITE_8(*bufp, 0);
}
break;
}
}
size_t
-fwrite_short(unsigned short val, FILE *f)
+fwrite_16_l(unsigned short val, FILE *f)
{
if (fputc(val & 0xFF, f) == EOF)
return 0;
}
size_t
-fwrite_long(unsigned long val, FILE *f)
+fwrite_32_l(unsigned long val, FILE *f)
{
if (fputc((int)(val & 0xFF), f) == EOF)
return 0;
return 0;
return 1;
}
+
+size_t
+fwrite_16_b(unsigned short val, FILE *f)
+{
+ if (fputc((val >> 8) & 0xFF, f) == EOF)
+ return 0;
+ if (fputc(val & 0xFF, f) == EOF)
+ return 0;
+ return 1;
+}
+
+size_t
+fwrite_32_b(unsigned long val, FILE *f)
+{
+ if (fputc((int)((val >> 24) & 0xFF), f) == EOF)
+ return 0;
+ if (fputc((int)((val >> 16) & 0xFF), f) == EOF)
+ return 0;
+ if (fputc((int)((val >> 8) & 0xFF), f) == EOF)
+ return 0;
+ if (fputc((int)(val & 0xFF), f) == EOF)
+ return 0;
+ return 1;
+}
/* $IdPath$
- * Little-endian file functions header file.
+ * Big and little endian file functions header file.
*
* Copyright (C) 2001 Peter Johnson
*
/* These functions only work properly if p is an (unsigned char *) */
-#define WRITE_BYTE(ptr, val) \
+#define WRITE_8(ptr, val) \
*((ptr)++) = (unsigned char)((val) & 0xFF)
-#define WRITE_SHORT(ptr, val) \
+#define WRITE_16_L(ptr, val) \
do { \
*((ptr)++) = (unsigned char)((val) & 0xFF); \
*((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
} while (0)
-#define WRITE_LONG(ptr, val) \
+#define WRITE_32_L(ptr, val) \
do { \
*((ptr)++) = (unsigned char)((val) & 0xFF); \
*((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
*((ptr)++) = (unsigned char)(((val) >> 24) & 0xFF); \
} while (0)
+#define WRITE_16_B(ptr, val) \
+ do { \
+ *((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
+ *((ptr)++) = (unsigned char)((val) & 0xFF); \
+ } while (0)
+
+#define WRITE_32_B(ptr, val) \
+ do { \
+ *((ptr)++) = (unsigned char)(((val) >> 24) & 0xFF); \
+ *((ptr)++) = (unsigned char)(((val) >> 16) & 0xFF); \
+ *((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
+ *((ptr)++) = (unsigned char)((val) & 0xFF); \
+ } while (0)
+
+
/* Non-incrementing versions of the above. */
-#define SAVE_BYTE(ptr, val) \
+#define SAVE_8(ptr, val) \
*(ptr) = (unsigned char)((val) & 0xFF)
-#define SAVE_SHORT(ptr, val) \
+#define SAVE_16_L(ptr, val) \
do { \
*(ptr) = (unsigned char)((val) & 0xFF); \
*((ptr)+1) = (unsigned char)(((val) >> 8) & 0xFF); \
} while (0)
-#define SAVE_LONG(ptr, val) \
+#define SAVE_32_L(ptr, val) \
do { \
*(ptr) = (unsigned char)((val) & 0xFF); \
*((ptr)+1) = (unsigned char)(((val) >> 8) & 0xFF); \
*((ptr)+3) = (unsigned char)(((val) >> 24) & 0xFF); \
} while (0)
+#define SAVE_16_B(ptr, val) \
+ do { \
+ *(ptr) = (unsigned char)(((val) >> 8) & 0xFF); \
+ *((ptr)+1) = (unsigned char)((val) & 0xFF); \
+ } while (0)
+
+#define SAVE_32_B(ptr, val) \
+ do { \
+ *(ptr) = (unsigned char)(((val) >> 24) & 0xFF); \
+ *((ptr)+1) = (unsigned char)(((val) >> 16) & 0xFF); \
+ *((ptr)+2) = (unsigned char)(((val) >> 8) & 0xFF); \
+ *((ptr)+3) = (unsigned char)((val) & 0xFF); \
+ } while (0)
+
/* Direct-to-file versions of the above. Using the above macros and a single
* fwrite() will probably be faster than calling these functions many times.
* These functions return 1 if the write was successful, 0 if not (so their
* return values can be used like the return value from fwrite()).
*/
-size_t fwrite_short(unsigned short val, FILE *f);
-size_t fwrite_long(unsigned long val, FILE *f);
+size_t fwrite_16_l(unsigned short val, FILE *f);
+size_t fwrite_32_l(unsigned long val, FILE *f);
+size_t fwrite_16_b(unsigned short val, FILE *f);
+size_t fwrite_32_b(unsigned long val, FILE *f);
/* Read/Load versions. val is the variable to receive the data. */
-#define READ_BYTE(val, ptr) \
+#define READ_8(val, ptr) \
(val) = *((ptr)++) & 0xFF
-#define READ_SHORT(val, ptr) \
+#define READ_16_L(val, ptr) \
do { \
(val) = *((ptr)++) & 0xFF; \
(val) |= (*((ptr)++) & 0xFF) << 8; \
} while (0)
-#define READ_LONG(val, ptr) \
+#define READ_32_L(val, ptr) \
do { \
(val) = *((ptr)++) & 0xFF; \
(val) |= (*((ptr)++) & 0xFF) << 8; \
(val) |= (*((ptr)++) & 0xFF) << 24; \
} while (0)
+#define READ_16_B(val, ptr) \
+ do { \
+ (val) = (*((ptr)++) & 0xFF) << 8; \
+ (val) |= *((ptr)++) & 0xFF; \
+ } while (0)
+
+#define READ_32_B(val, ptr) \
+ do { \
+ (val) = (*((ptr)++) & 0xFF) << 24; \
+ (val) |= (*((ptr)++) & 0xFF) << 16; \
+ (val) |= (*((ptr)++) & 0xFF) << 8; \
+ (val) |= *((ptr)++) & 0xFF; \
+ } while (0)
+
/* Non-incrementing versions of the above. */
-#define LOAD_BYTE(val, ptr) \
+#define LOAD_8(val, ptr) \
(val) = *(ptr) & 0xFF
-#define LOAD_SHORT(val, ptr) \
+#define LOAD_16_L(val, ptr) \
do { \
(val) = *(ptr) & 0xFF; \
(val) |= (*((ptr)+1) & 0xFF) << 8; \
} while (0)
-#define LOAD_LONG(val, ptr) \
+#define LOAD_32_L(val, ptr) \
do { \
(val) = (unsigned long)(*(ptr) & 0xFF); \
(val) |= (unsigned long)((*((ptr)+1) & 0xFF) << 8); \
(val) |= (unsigned long)((*((ptr)+3) & 0xFF) << 24); \
} while (0)
+#define LOAD_16_B(val, ptr) \
+ do { \
+ (val) = (*(ptr) & 0xFF) << 8; \
+ (val) |= *((ptr)+1) & 0xFF; \
+ } while (0)
+
+#define LOAD_32_B(val, ptr) \
+ do { \
+ (val) = (unsigned long)((*(ptr) & 0xFF) << 24); \
+ (val) |= (unsigned long)((*((ptr)+1) & 0xFF) << 16); \
+ (val) |= (unsigned long)((*((ptr)+2) & 0xFF) << 8); \
+ (val) |= (unsigned long)(*((ptr)+3) & 0xFF); \
+ } while (0)
+
#endif
return 1;
}
- LOAD_LONG(*ret_val, &t[0]);
+ LOAD_32_L(*ret_val, &t[0]);
return 0;
}
case INTNUM_UL:
ul = intn->val.ul;
while (size-- > 0) {
- WRITE_BYTE(ptr, ul);
+ WRITE_8(ptr, ul);
if (ul != 0)
ul >>= 8;
}
#include "util.h"
/*@unused@*/ RCSID("$IdPath$");
+#include "file.h"
+
#include "globals.h"
#include "errwarn.h"
#include "intnum.h"
+#include "floatnum.h"
#include "expr.h"
#include "bytecode.h"
x86_bc_resolve,
x86_bc_tobytes
},
+ x86_floatnum_tobytes,
+ x86_intnum_tobytes,
x86_get_reg_size,
x86_reg_print,
x86_segreg_print,
void x86_handle_seg_override(effaddr *ea, unsigned long segreg);
+int x86_floatnum_tobytes(const floatnum *flt, unsigned char **bufp,
+ unsigned long valsize, const expr *e);
+int x86_intnum_tobytes(const intnum *intn, unsigned char **bufp,
+ unsigned long valsize, const expr *e,
+ const bytecode *bc, int rel);
+
unsigned int x86_get_reg_size(unsigned long reg);
void x86_reg_print(FILE *f, unsigned long reg);
/* Prefixes */
if (insn->lockrep_pre != 0)
- WRITE_BYTE(*bufp, insn->lockrep_pre);
+ WRITE_8(*bufp, insn->lockrep_pre);
if (ea && ead->segment != 0)
- WRITE_BYTE(*bufp, ead->segment);
+ WRITE_8(*bufp, ead->segment);
if (insn->opersize != 0 && insn->opersize != insn->mode_bits)
- WRITE_BYTE(*bufp, 0x66);
+ WRITE_8(*bufp, 0x66);
if (insn->addrsize != 0 && insn->addrsize != insn->mode_bits)
- WRITE_BYTE(*bufp, 0x67);
+ WRITE_8(*bufp, 0x67);
/* Opcode */
for (i=0; i<insn->opcode_len; i++)
- WRITE_BYTE(*bufp, insn->opcode[i]);
+ WRITE_8(*bufp, insn->opcode[i]);
/* Effective address: ModR/M (if required), SIB (if required), and
* displacement (if required).
if (ead->need_modrm) {
if (!ead->valid_modrm)
InternalError(_("invalid Mod/RM in x86 tobytes_insn"));
- WRITE_BYTE(*bufp, ead->modrm);
+ WRITE_8(*bufp, ead->modrm);
}
if (ead->need_sib) {
if (!ead->valid_sib)
InternalError(_("invalid SIB in x86 tobytes_insn"));
- WRITE_BYTE(*bufp, ead->sib);
+ WRITE_8(*bufp, ead->sib);
}
if (ea->disp) {
* write out 0 value.
*/
for (i=0; i<ea->len; i++)
- WRITE_BYTE(*bufp, 0);
+ WRITE_8(*bufp, 0);
}
}
}
/* Prefixes */
if (jmprel->lockrep_pre != 0)
- WRITE_BYTE(*bufp, jmprel->lockrep_pre);
+ WRITE_8(*bufp, jmprel->lockrep_pre);
/* FIXME: branch hints! */
if (jmprel->opersize != 0 && jmprel->opersize != jmprel->mode_bits)
- WRITE_BYTE(*bufp, 0x66);
+ WRITE_8(*bufp, 0x66);
if (jmprel->addrsize != 0 && jmprel->addrsize != jmprel->mode_bits)
- WRITE_BYTE(*bufp, 0x67);
+ WRITE_8(*bufp, 0x67);
/* As opersize may be 0, figure out its "real" value. */
opersize = (jmprel->opersize == 0) ? jmprel->mode_bits :
/* Opcode */
for (i=0; i<jmprel->shortop.opcode_len; i++)
- WRITE_BYTE(*bufp, jmprel->shortop.opcode[i]);
+ WRITE_8(*bufp, jmprel->shortop.opcode[i]);
/* Relative displacement */
if (output_expr(&jmprel->target, bufp, 1, sect, bc, 1, d))
/* Opcode */
for (i=0; i<jmprel->nearop.opcode_len; i++)
- WRITE_BYTE(*bufp, jmprel->nearop.opcode[i]);
+ WRITE_8(*bufp, jmprel->nearop.opcode[i]);
/* Relative displacement */
if (output_expr(&jmprel->target, bufp,
return 0;
}
+int
+x86_intnum_tobytes(const intnum *intn, unsigned char **bufp,
+ unsigned long valsize, const expr *e, const bytecode *bc,
+ int rel)
+{
+ if (rel) {
+ long val;
+ if (valsize != 1 && valsize != 2 && valsize != 4)
+ InternalError(_("tried to do PC-relative offset from invalid sized value"));
+ val = intnum_get_uint(intn);
+ val -= bc->len;
+ switch (valsize) {
+ case 1:
+ WRITE_8(*bufp, val);
+ break;
+ case 2:
+ WRITE_16_L(*bufp, val);
+ break;
+ case 4:
+ WRITE_32_L(*bufp, val);
+ break;
+ }
+ } else {
+ /* Write value out. */
+ intnum_get_sized(intn, *bufp, (size_t)valsize);
+ *bufp += valsize;
+ }
+ return 0;
+}
}
return 1;
}
+
+int
+x86_floatnum_tobytes(const floatnum *flt, unsigned char **bufp,
+ unsigned long valsize, const expr *e)
+{
+ int fltret;
+
+ if (!floatnum_check_size(flt, (size_t)valsize)) {
+ ErrorAt(e->line, _("invalid floating point constant size"));
+ return 1;
+ }
+
+ fltret = floatnum_get_sized(flt, *bufp, (size_t)valsize);
+ if (fltret < 0) {
+ ErrorAt(e->line, _("underflow in floating point expression"));
+ return 1;
+ }
+ if (fltret > 0) {
+ ErrorAt(e->line, _("overflow in floating point expression"));
+ return 1;
+ }
+ *bufp += valsize;
+ return 0;
+}
#include "expr-int.h"
#include "bc-int.h"
+#include "arch.h"
#include "objfmt.h"
/*@observer@*/ const bytecode *bc, int rel,
/*@unused@*/ /*@null@*/ void *d)
{
- /*@dependent@*/ /*@null@*/ const intnum *num;
+ /*@dependent@*/ /*@null@*/ const intnum *intn;
/*@dependent@*/ /*@null@*/ const floatnum *flt;
assert(info != NULL);
/* Handle floating point expressions */
flt = expr_get_floatnum(ep);
- if (flt) {
- int fltret;
-
- if (!floatnum_check_size(flt, (size_t)valsize)) {
- ErrorAt((*ep)->line, _("invalid floating point constant size"));
- return 1;
- }
-
- fltret = floatnum_get_sized(flt, *bufp, (size_t)valsize);
- if (fltret < 0) {
- ErrorAt((*ep)->line, _("underflow in floating point expression"));
- return 1;
- }
- if (fltret > 0) {
- ErrorAt((*ep)->line, _("overflow in floating point expression"));
- return 1;
- }
- *bufp += valsize;
- return 0;
- }
+ if (flt)
+ return cur_arch->floatnum_tobytes(flt, bufp, valsize, *ep);
/* Handle integer expressions */
- num = expr_get_intnum(ep, NULL);
- if (num) {
- if (rel) {
- long val;
- if (valsize != 1 && valsize != 2 && valsize != 4)
- InternalError(_("tried to do PC-relative offset from invalid sized value"));
- val = intnum_get_uint(num);
- val -= bc->len;
- switch (valsize) {
- case 1:
- WRITE_BYTE(*bufp, val);
- break;
- case 2:
- WRITE_SHORT(*bufp, val);
- break;
- case 4:
- WRITE_LONG(*bufp, val);
- break;
- }
- } else {
- /* Write value out. */
- intnum_get_sized(num, *bufp, (size_t)valsize);
- *bufp += valsize;
- }
- return 0;
- }
+ intn = expr_get_intnum(ep, NULL);
+ if (intn)
+ return cur_arch->intnum_tobytes(intn, bufp, valsize, *ep, bc, rel);
/* Check for complex float expressions */
if (expr_contains(*ep, EXPR_FLOAT)) {
output_expr_func output_expr);
} bc;
+ /* Functions to output floats and integers, architecture-specific because
+ * of endianness. Returns nonzero on error, otherwise updates bufp by
+ * valsize (bytes saved to bufp). For intnums, rel indicates a relative
+ * displacement, and bc is the containing bytecode to compute it from.
+ */
+ int (*floatnum_tobytes) (const floatnum *flt, unsigned char **bufp,
+ unsigned long valsize, const expr *e);
+ int (*intnum_tobytes) (const intnum *intn, unsigned char **bufp,
+ unsigned long valsize, const expr *e,
+ const bytecode *bc, int rel);
+
/* Gets the equivalent register size in bytes. Returns 0 if there is no
* suitable equivalent size.
*/
#include "util.h"
/*@unused@*/ RCSID("$IdPath$");
+#include "file.h"
+
#include "globals.h"
#include "errwarn.h"
#include "intnum.h"
+#include "floatnum.h"
#include "expr.h"
#include "bytecode.h"
x86_bc_resolve,
x86_bc_tobytes
},
+ x86_floatnum_tobytes,
+ x86_intnum_tobytes,
x86_get_reg_size,
x86_reg_print,
x86_segreg_print,
void x86_handle_seg_override(effaddr *ea, unsigned long segreg);
+int x86_floatnum_tobytes(const floatnum *flt, unsigned char **bufp,
+ unsigned long valsize, const expr *e);
+int x86_intnum_tobytes(const intnum *intn, unsigned char **bufp,
+ unsigned long valsize, const expr *e,
+ const bytecode *bc, int rel);
+
unsigned int x86_get_reg_size(unsigned long reg);
void x86_reg_print(FILE *f, unsigned long reg);
/* Prefixes */
if (insn->lockrep_pre != 0)
- WRITE_BYTE(*bufp, insn->lockrep_pre);
+ WRITE_8(*bufp, insn->lockrep_pre);
if (ea && ead->segment != 0)
- WRITE_BYTE(*bufp, ead->segment);
+ WRITE_8(*bufp, ead->segment);
if (insn->opersize != 0 && insn->opersize != insn->mode_bits)
- WRITE_BYTE(*bufp, 0x66);
+ WRITE_8(*bufp, 0x66);
if (insn->addrsize != 0 && insn->addrsize != insn->mode_bits)
- WRITE_BYTE(*bufp, 0x67);
+ WRITE_8(*bufp, 0x67);
/* Opcode */
for (i=0; i<insn->opcode_len; i++)
- WRITE_BYTE(*bufp, insn->opcode[i]);
+ WRITE_8(*bufp, insn->opcode[i]);
/* Effective address: ModR/M (if required), SIB (if required), and
* displacement (if required).
if (ead->need_modrm) {
if (!ead->valid_modrm)
InternalError(_("invalid Mod/RM in x86 tobytes_insn"));
- WRITE_BYTE(*bufp, ead->modrm);
+ WRITE_8(*bufp, ead->modrm);
}
if (ead->need_sib) {
if (!ead->valid_sib)
InternalError(_("invalid SIB in x86 tobytes_insn"));
- WRITE_BYTE(*bufp, ead->sib);
+ WRITE_8(*bufp, ead->sib);
}
if (ea->disp) {
* write out 0 value.
*/
for (i=0; i<ea->len; i++)
- WRITE_BYTE(*bufp, 0);
+ WRITE_8(*bufp, 0);
}
}
}
/* Prefixes */
if (jmprel->lockrep_pre != 0)
- WRITE_BYTE(*bufp, jmprel->lockrep_pre);
+ WRITE_8(*bufp, jmprel->lockrep_pre);
/* FIXME: branch hints! */
if (jmprel->opersize != 0 && jmprel->opersize != jmprel->mode_bits)
- WRITE_BYTE(*bufp, 0x66);
+ WRITE_8(*bufp, 0x66);
if (jmprel->addrsize != 0 && jmprel->addrsize != jmprel->mode_bits)
- WRITE_BYTE(*bufp, 0x67);
+ WRITE_8(*bufp, 0x67);
/* As opersize may be 0, figure out its "real" value. */
opersize = (jmprel->opersize == 0) ? jmprel->mode_bits :
/* Opcode */
for (i=0; i<jmprel->shortop.opcode_len; i++)
- WRITE_BYTE(*bufp, jmprel->shortop.opcode[i]);
+ WRITE_8(*bufp, jmprel->shortop.opcode[i]);
/* Relative displacement */
if (output_expr(&jmprel->target, bufp, 1, sect, bc, 1, d))
/* Opcode */
for (i=0; i<jmprel->nearop.opcode_len; i++)
- WRITE_BYTE(*bufp, jmprel->nearop.opcode[i]);
+ WRITE_8(*bufp, jmprel->nearop.opcode[i]);
/* Relative displacement */
if (output_expr(&jmprel->target, bufp,
return 0;
}
+int
+x86_intnum_tobytes(const intnum *intn, unsigned char **bufp,
+ unsigned long valsize, const expr *e, const bytecode *bc,
+ int rel)
+{
+ if (rel) {
+ long val;
+ if (valsize != 1 && valsize != 2 && valsize != 4)
+ InternalError(_("tried to do PC-relative offset from invalid sized value"));
+ val = intnum_get_uint(intn);
+ val -= bc->len;
+ switch (valsize) {
+ case 1:
+ WRITE_8(*bufp, val);
+ break;
+ case 2:
+ WRITE_16_L(*bufp, val);
+ break;
+ case 4:
+ WRITE_32_L(*bufp, val);
+ break;
+ }
+ } else {
+ /* Write value out. */
+ intnum_get_sized(intn, *bufp, (size_t)valsize);
+ *bufp += valsize;
+ }
+ return 0;
+}
}
return 1;
}
+
+int
+x86_floatnum_tobytes(const floatnum *flt, unsigned char **bufp,
+ unsigned long valsize, const expr *e)
+{
+ int fltret;
+
+ if (!floatnum_check_size(flt, (size_t)valsize)) {
+ ErrorAt(e->line, _("invalid floating point constant size"));
+ return 1;
+ }
+
+ fltret = floatnum_get_sized(flt, *bufp, (size_t)valsize);
+ if (fltret < 0) {
+ ErrorAt(e->line, _("underflow in floating point expression"));
+ return 1;
+ }
+ if (fltret > 0) {
+ ErrorAt(e->line, _("overflow in floating point expression"));
+ return 1;
+ }
+ *bufp += valsize;
+ return 0;
+}
if (slen > 0) {
slen = bc_data->size-slen;
for (i=0; i<slen; i++)
- WRITE_BYTE(*bufp, 0);
+ WRITE_8(*bufp, 0);
}
break;
}
}
size_t
-fwrite_short(unsigned short val, FILE *f)
+fwrite_16_l(unsigned short val, FILE *f)
{
if (fputc(val & 0xFF, f) == EOF)
return 0;
}
size_t
-fwrite_long(unsigned long val, FILE *f)
+fwrite_32_l(unsigned long val, FILE *f)
{
if (fputc((int)(val & 0xFF), f) == EOF)
return 0;
return 0;
return 1;
}
+
+size_t
+fwrite_16_b(unsigned short val, FILE *f)
+{
+ if (fputc((val >> 8) & 0xFF, f) == EOF)
+ return 0;
+ if (fputc(val & 0xFF, f) == EOF)
+ return 0;
+ return 1;
+}
+
+size_t
+fwrite_32_b(unsigned long val, FILE *f)
+{
+ if (fputc((int)((val >> 24) & 0xFF), f) == EOF)
+ return 0;
+ if (fputc((int)((val >> 16) & 0xFF), f) == EOF)
+ return 0;
+ if (fputc((int)((val >> 8) & 0xFF), f) == EOF)
+ return 0;
+ if (fputc((int)(val & 0xFF), f) == EOF)
+ return 0;
+ return 1;
+}
/* $IdPath$
- * Little-endian file functions header file.
+ * Big and little endian file functions header file.
*
* Copyright (C) 2001 Peter Johnson
*
/* These functions only work properly if p is an (unsigned char *) */
-#define WRITE_BYTE(ptr, val) \
+#define WRITE_8(ptr, val) \
*((ptr)++) = (unsigned char)((val) & 0xFF)
-#define WRITE_SHORT(ptr, val) \
+#define WRITE_16_L(ptr, val) \
do { \
*((ptr)++) = (unsigned char)((val) & 0xFF); \
*((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
} while (0)
-#define WRITE_LONG(ptr, val) \
+#define WRITE_32_L(ptr, val) \
do { \
*((ptr)++) = (unsigned char)((val) & 0xFF); \
*((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
*((ptr)++) = (unsigned char)(((val) >> 24) & 0xFF); \
} while (0)
+#define WRITE_16_B(ptr, val) \
+ do { \
+ *((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
+ *((ptr)++) = (unsigned char)((val) & 0xFF); \
+ } while (0)
+
+#define WRITE_32_B(ptr, val) \
+ do { \
+ *((ptr)++) = (unsigned char)(((val) >> 24) & 0xFF); \
+ *((ptr)++) = (unsigned char)(((val) >> 16) & 0xFF); \
+ *((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
+ *((ptr)++) = (unsigned char)((val) & 0xFF); \
+ } while (0)
+
+
/* Non-incrementing versions of the above. */
-#define SAVE_BYTE(ptr, val) \
+#define SAVE_8(ptr, val) \
*(ptr) = (unsigned char)((val) & 0xFF)
-#define SAVE_SHORT(ptr, val) \
+#define SAVE_16_L(ptr, val) \
do { \
*(ptr) = (unsigned char)((val) & 0xFF); \
*((ptr)+1) = (unsigned char)(((val) >> 8) & 0xFF); \
} while (0)
-#define SAVE_LONG(ptr, val) \
+#define SAVE_32_L(ptr, val) \
do { \
*(ptr) = (unsigned char)((val) & 0xFF); \
*((ptr)+1) = (unsigned char)(((val) >> 8) & 0xFF); \
*((ptr)+3) = (unsigned char)(((val) >> 24) & 0xFF); \
} while (0)
+#define SAVE_16_B(ptr, val) \
+ do { \
+ *(ptr) = (unsigned char)(((val) >> 8) & 0xFF); \
+ *((ptr)+1) = (unsigned char)((val) & 0xFF); \
+ } while (0)
+
+#define SAVE_32_B(ptr, val) \
+ do { \
+ *(ptr) = (unsigned char)(((val) >> 24) & 0xFF); \
+ *((ptr)+1) = (unsigned char)(((val) >> 16) & 0xFF); \
+ *((ptr)+2) = (unsigned char)(((val) >> 8) & 0xFF); \
+ *((ptr)+3) = (unsigned char)((val) & 0xFF); \
+ } while (0)
+
/* Direct-to-file versions of the above. Using the above macros and a single
* fwrite() will probably be faster than calling these functions many times.
* These functions return 1 if the write was successful, 0 if not (so their
* return values can be used like the return value from fwrite()).
*/
-size_t fwrite_short(unsigned short val, FILE *f);
-size_t fwrite_long(unsigned long val, FILE *f);
+size_t fwrite_16_l(unsigned short val, FILE *f);
+size_t fwrite_32_l(unsigned long val, FILE *f);
+size_t fwrite_16_b(unsigned short val, FILE *f);
+size_t fwrite_32_b(unsigned long val, FILE *f);
/* Read/Load versions. val is the variable to receive the data. */
-#define READ_BYTE(val, ptr) \
+#define READ_8(val, ptr) \
(val) = *((ptr)++) & 0xFF
-#define READ_SHORT(val, ptr) \
+#define READ_16_L(val, ptr) \
do { \
(val) = *((ptr)++) & 0xFF; \
(val) |= (*((ptr)++) & 0xFF) << 8; \
} while (0)
-#define READ_LONG(val, ptr) \
+#define READ_32_L(val, ptr) \
do { \
(val) = *((ptr)++) & 0xFF; \
(val) |= (*((ptr)++) & 0xFF) << 8; \
(val) |= (*((ptr)++) & 0xFF) << 24; \
} while (0)
+#define READ_16_B(val, ptr) \
+ do { \
+ (val) = (*((ptr)++) & 0xFF) << 8; \
+ (val) |= *((ptr)++) & 0xFF; \
+ } while (0)
+
+#define READ_32_B(val, ptr) \
+ do { \
+ (val) = (*((ptr)++) & 0xFF) << 24; \
+ (val) |= (*((ptr)++) & 0xFF) << 16; \
+ (val) |= (*((ptr)++) & 0xFF) << 8; \
+ (val) |= *((ptr)++) & 0xFF; \
+ } while (0)
+
/* Non-incrementing versions of the above. */
-#define LOAD_BYTE(val, ptr) \
+#define LOAD_8(val, ptr) \
(val) = *(ptr) & 0xFF
-#define LOAD_SHORT(val, ptr) \
+#define LOAD_16_L(val, ptr) \
do { \
(val) = *(ptr) & 0xFF; \
(val) |= (*((ptr)+1) & 0xFF) << 8; \
} while (0)
-#define LOAD_LONG(val, ptr) \
+#define LOAD_32_L(val, ptr) \
do { \
(val) = (unsigned long)(*(ptr) & 0xFF); \
(val) |= (unsigned long)((*((ptr)+1) & 0xFF) << 8); \
(val) |= (unsigned long)((*((ptr)+3) & 0xFF) << 24); \
} while (0)
+#define LOAD_16_B(val, ptr) \
+ do { \
+ (val) = (*(ptr) & 0xFF) << 8; \
+ (val) |= *((ptr)+1) & 0xFF; \
+ } while (0)
+
+#define LOAD_32_B(val, ptr) \
+ do { \
+ (val) = (unsigned long)((*(ptr) & 0xFF) << 24); \
+ (val) |= (unsigned long)((*((ptr)+1) & 0xFF) << 16); \
+ (val) |= (unsigned long)((*((ptr)+2) & 0xFF) << 8); \
+ (val) |= (unsigned long)(*((ptr)+3) & 0xFF); \
+ } while (0)
+
#endif
return 1;
}
- LOAD_LONG(*ret_val, &t[0]);
+ LOAD_32_L(*ret_val, &t[0]);
return 0;
}
case INTNUM_UL:
ul = intn->val.ul;
while (size-- > 0) {
- WRITE_BYTE(ptr, ul);
+ WRITE_8(ptr, ul);
if (ul != 0)
ul >>= 8;
}
#include "expr-int.h"
#include "bc-int.h"
+#include "arch.h"
#include "objfmt.h"
/*@observer@*/ const bytecode *bc, int rel,
/*@unused@*/ /*@null@*/ void *d)
{
- /*@dependent@*/ /*@null@*/ const intnum *num;
+ /*@dependent@*/ /*@null@*/ const intnum *intn;
/*@dependent@*/ /*@null@*/ const floatnum *flt;
assert(info != NULL);
/* Handle floating point expressions */
flt = expr_get_floatnum(ep);
- if (flt) {
- int fltret;
-
- if (!floatnum_check_size(flt, (size_t)valsize)) {
- ErrorAt((*ep)->line, _("invalid floating point constant size"));
- return 1;
- }
-
- fltret = floatnum_get_sized(flt, *bufp, (size_t)valsize);
- if (fltret < 0) {
- ErrorAt((*ep)->line, _("underflow in floating point expression"));
- return 1;
- }
- if (fltret > 0) {
- ErrorAt((*ep)->line, _("overflow in floating point expression"));
- return 1;
- }
- *bufp += valsize;
- return 0;
- }
+ if (flt)
+ return cur_arch->floatnum_tobytes(flt, bufp, valsize, *ep);
/* Handle integer expressions */
- num = expr_get_intnum(ep, NULL);
- if (num) {
- if (rel) {
- long val;
- if (valsize != 1 && valsize != 2 && valsize != 4)
- InternalError(_("tried to do PC-relative offset from invalid sized value"));
- val = intnum_get_uint(num);
- val -= bc->len;
- switch (valsize) {
- case 1:
- WRITE_BYTE(*bufp, val);
- break;
- case 2:
- WRITE_SHORT(*bufp, val);
- break;
- case 4:
- WRITE_LONG(*bufp, val);
- break;
- }
- } else {
- /* Write value out. */
- intnum_get_sized(num, *bufp, (size_t)valsize);
- *bufp += valsize;
- }
- return 0;
- }
+ intn = expr_get_intnum(ep, NULL);
+ if (intn)
+ return cur_arch->intnum_tobytes(intn, bufp, valsize, *ep, bc, rel);
/* Check for complex float expressions */
if (expr_contains(*ep, EXPR_FLOAT)) {