mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-03-31 18:20:22 +08:00
New backend interface - assembler internals #1
This provides the first pass of assembler internals for a new, richer, backend interface. It also reduces the amount of data carried in function parameters inside the assembler. The new interface is in the form of a structure, which will contain substantially more information that the previous interface. This will allow things like ELF GOT32X and Mach-O X86_64_RELOC_BRANCH relocations to be reliably emitted. This provides the initial set of structures. Future additions should include: 1. Pass down the base symbol, if any. 2. Segments should be a structure rather than a number, and the horrible hack of adding one for a segment reference should be removed (OUT_SEGMENT replaces it.) Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
This commit is contained in:
parent
9938bb6333
commit
a77692b34d
1088
asm/assemble.c
1088
asm/assemble.c
File diff suppressed because it is too large
Load Diff
@ -166,7 +166,7 @@ static void list_cleanup(void)
|
||||
fclose(listfp);
|
||||
}
|
||||
|
||||
static void list_out(int32_t offset, char *str)
|
||||
static void list_out(int64_t offset, char *str)
|
||||
{
|
||||
if (strlen(listdata) + strlen(str) > LIST_HEXBIT) {
|
||||
strcat(listdata, "-");
|
||||
@ -177,7 +177,7 @@ static void list_out(int32_t offset, char *str)
|
||||
strcat(listdata, str);
|
||||
}
|
||||
|
||||
static void list_address(int32_t offset, const char *brackets,
|
||||
static void list_address(int64_t offset, const char *brackets,
|
||||
int64_t addr, int size)
|
||||
{
|
||||
char q[20];
|
||||
@ -196,21 +196,22 @@ static void list_address(int32_t offset, const char *brackets,
|
||||
list_out(offset, q);
|
||||
}
|
||||
|
||||
static void list_output(int32_t offset, const void *data,
|
||||
enum out_type type, uint64_t size)
|
||||
static void list_output(const struct out_data *data)
|
||||
{
|
||||
char q[20];
|
||||
uint64_t size = data->size;
|
||||
uint64_t offset = data->offset;
|
||||
|
||||
if (!listp || suppress || user_nolist)
|
||||
return;
|
||||
|
||||
switch (type) {
|
||||
switch (data->type) {
|
||||
case OUT_RAWDATA:
|
||||
{
|
||||
uint8_t const *p = data;
|
||||
const uint8_t *p = data->data;
|
||||
|
||||
if (size == 0 && !listdata[0])
|
||||
listoffset = offset;
|
||||
listoffset = data->offset;
|
||||
while (size--) {
|
||||
HEX(q, *p);
|
||||
q[2] = '\0';
|
||||
@ -220,19 +221,11 @@ static void list_output(int32_t offset, const void *data,
|
||||
break;
|
||||
}
|
||||
case OUT_ADDRESS:
|
||||
list_address(offset, "[]", *(int64_t *)data, abs((int)size));
|
||||
case OUT_SEGMENT:
|
||||
list_address(offset, "[]", data->toffset, size);
|
||||
break;
|
||||
case OUT_REL1ADR:
|
||||
list_address(offset, "()", *(int64_t *)data, 1);
|
||||
break;
|
||||
case OUT_REL2ADR:
|
||||
list_address(offset, "()", *(int64_t *)data, 2);
|
||||
break;
|
||||
case OUT_REL4ADR:
|
||||
list_address(offset, "()", *(int64_t *)data, 4);
|
||||
break;
|
||||
case OUT_REL8ADR:
|
||||
list_address(offset, "()", *(int64_t *)data, 8);
|
||||
case OUT_RELADDR:
|
||||
list_address(offset, "()", data->toffset, size);
|
||||
break;
|
||||
case OUT_RESERVE:
|
||||
{
|
||||
@ -240,6 +233,8 @@ static void list_output(int32_t offset, const void *data,
|
||||
list_out(offset, q);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
panic();
|
||||
}
|
||||
}
|
||||
|
||||
@ -324,6 +319,10 @@ static void list_error(int severity, const char *pfx, const char *msg)
|
||||
list_emit();
|
||||
}
|
||||
|
||||
static void list_set_offset(uint64_t offset)
|
||||
{
|
||||
listoffset = offset;
|
||||
}
|
||||
|
||||
static const struct lfmt nasm_list = {
|
||||
list_init,
|
||||
@ -332,7 +331,8 @@ static const struct lfmt nasm_list = {
|
||||
list_line,
|
||||
list_uplevel,
|
||||
list_downlevel,
|
||||
list_error
|
||||
list_error,
|
||||
list_set_offset
|
||||
};
|
||||
|
||||
const struct lfmt *lfmt = &nasm_list;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* ----------------------------------------------------------------------- *
|
||||
*
|
||||
* Copyright 1996-2009 The NASM Authors - All Rights Reserved
|
||||
* Copyright 1996-2016 The NASM Authors - All Rights Reserved
|
||||
* See the file AUTHORS included with the NASM distribution for
|
||||
* the specific copyright holders.
|
||||
*
|
||||
@ -61,12 +61,9 @@ struct lfmt {
|
||||
* output-format interface, only OUT_ADDRESS will _always_ be
|
||||
* displayed as if it's relocatable, so ensure that any non-
|
||||
* relocatable address has been converted to OUT_RAWDATA by
|
||||
* then. Note that OUT_RAWDATA,0 is a valid data type, and is a
|
||||
* dummy call used to give the listing generator an offset to
|
||||
* work with when doing things like uplevel(LIST_TIMES) or
|
||||
* uplevel(LIST_INCBIN).
|
||||
* then.
|
||||
*/
|
||||
void (*output)(int32_t offset, const void *data, enum out_type type, uint64_t size);
|
||||
void (*output)(const struct out_data *data);
|
||||
|
||||
/*
|
||||
* Called to send a text line to the listing generator. The
|
||||
@ -100,6 +97,14 @@ struct lfmt {
|
||||
* Called on a warning or error, with the error message.
|
||||
*/
|
||||
void (*error)(int severity, const char *pfx, const char *msg);
|
||||
|
||||
/*
|
||||
* Update the current offset. Used to give the listing generator
|
||||
* an offset to work with when doing things like
|
||||
* uplevel(LIST_TIMES) or uplevel(LIST_INCBIN); see
|
||||
* list_set_offset();
|
||||
*/
|
||||
void (*set_offset)(uint64_t offset);
|
||||
};
|
||||
|
||||
extern const struct lfmt *lfmt;
|
||||
|
@ -1687,6 +1687,7 @@ static void assemble_file(char *fname, StrList **depend_ptr)
|
||||
|
||||
int64_t l = insn_size(location.segment, offs, sb, cpu,
|
||||
&output_ins);
|
||||
l *= output_ins.times;
|
||||
|
||||
/* if (using_debug_info) && output_ins.opcode != -1) */
|
||||
if (using_debug_info)
|
||||
|
@ -100,12 +100,43 @@ struct ofmt;
|
||||
*/
|
||||
enum out_type {
|
||||
OUT_RAWDATA, /* Plain bytes */
|
||||
OUT_ADDRESS, /* An address (symbol value) */
|
||||
OUT_RESERVE, /* Reserved bytes (RESB et al) */
|
||||
OUT_REL1ADR, /* 1-byte relative address */
|
||||
OUT_REL2ADR, /* 2-byte relative address */
|
||||
OUT_REL4ADR, /* 4-byte relative address */
|
||||
OUT_REL8ADR /* 8-byte relative address */
|
||||
OUT_ADDRESS, /* An address (symbol value) */
|
||||
OUT_RELADDR, /* A relative address (relative to instruction end) */
|
||||
OUT_SEGMENT, /* A segment number */
|
||||
|
||||
/* These are temporary until the backend change */
|
||||
OUT_REL1ADR,
|
||||
OUT_REL2ADR,
|
||||
OUT_REL4ADR,
|
||||
OUT_REL8ADR
|
||||
};
|
||||
|
||||
enum out_sign {
|
||||
OUT_WRAP, /* Undefined signedness (wraps) */
|
||||
OUT_SIGNED, /* Value is signed */
|
||||
OUT_UNSIGNED /* Value is unsigned */
|
||||
};
|
||||
|
||||
/*
|
||||
* The data we send down to the backend.
|
||||
* XXX: We still want to push down the base address symbol if
|
||||
* available, and replace the segment numbers with a structure.
|
||||
*/
|
||||
struct out_data {
|
||||
int64_t offset; /* Offset within segment */
|
||||
int32_t segment; /* Segment written to */
|
||||
enum out_type type; /* See above */
|
||||
enum out_sign sign; /* See above */
|
||||
int inslen; /* Length of instruction */
|
||||
int insoffs; /* Offset inside instruction */
|
||||
int bits; /* Bits mode of compilation */
|
||||
uint64_t size; /* Size of output */
|
||||
const struct itemplate *itemp; /* Instruction template */
|
||||
const void *data; /* Data for OUT_RAWDATA */
|
||||
uint64_t toffset; /* Target address offset for relocation */
|
||||
int32_t tsegment; /* Target segment for relocation */
|
||||
int32_t twrt; /* Relocation with respect to */
|
||||
};
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user