Merge remote-tracking branch 'origin/nasm-2.13.xx'

This commit is contained in:
H. Peter Anvin 2017-05-01 21:25:14 -07:00
commit 20f6c253cd
15 changed files with 247 additions and 183 deletions

View file

@ -495,7 +495,7 @@ static inline void out_segment(struct out_data *data,
data->type = OUT_SEGMENT;
data->sign = OUT_UNSIGNED;
data->size = 2;
data->toffset = opx->offset;
data->toffset = opx->offset; /* Is this really needed/wanted? */
data->tsegment = ofmt->segbase(opx->segment + 1);
data->twrt = opx->wrt;
out(data);
@ -546,7 +546,6 @@ int64_t assemble(int32_t segment, int64_t start, int bits, insn *instruction)
struct out_data data;
const struct itemplate *temp;
enum match_result m;
int32_t itimes;
int64_t wsize; /* size for DB etc. */
nasm_zero(data);
@ -562,51 +561,40 @@ int64_t assemble(int32_t segment, int64_t start, int bits, insn *instruction)
if (wsize) {
extop *e;
int32_t t = instruction->times;
if (t < 0)
nasm_panic(0, "instruction->times < 0 (%"PRId32") in assemble()", t);
while (t--) { /* repeat TIMES times */
list_for_each(e, instruction->eops) {
if (e->type == EOT_DB_NUMBER) {
if (wsize > 8) {
nasm_error(ERR_NONFATAL,
"integer supplied to a DT, DO or DY"
" instruction");
} else {
data.insoffs = 0;
data.type = e->relative ? OUT_RELADDR : OUT_ADDRESS;
data.inslen = data.size = wsize;
data.toffset = e->offset;
data.tsegment = e->segment;
data.twrt = e->wrt;
data.relbase = 0;
out(&data);
}
} else if (e->type == EOT_DB_STRING ||
e->type == EOT_DB_STRING_FREE) {
int align = e->stringlen % wsize;
if (align)
align = wsize - align;
list_for_each(e, instruction->eops) {
if (e->type == EOT_DB_NUMBER) {
if (wsize > 8) {
nasm_error(ERR_NONFATAL,
"integer supplied to a DT, DO, DY or DZ"
" instruction");
} else {
data.insoffs = 0;
data.inslen = e->stringlen + align;
out_rawdata(&data, e->stringval, e->stringlen);
out_rawdata(&data, zero_buffer, align);
data.type = e->relative ? OUT_RELADDR : OUT_ADDRESS;
data.inslen = data.size = wsize;
data.toffset = e->offset;
data.tsegment = e->segment;
data.twrt = e->wrt;
data.relbase = 0;
out(&data);
}
}
if (t > 0 && t == instruction->times - 1) {
lfmt->set_offset(data.offset);
lfmt->uplevel(LIST_TIMES);
} else if (e->type == EOT_DB_STRING ||
e->type == EOT_DB_STRING_FREE) {
int align = e->stringlen % wsize;
if (align)
align = wsize - align;
data.insoffs = 0;
data.inslen = e->stringlen + align;
out_rawdata(&data, e->stringval, e->stringlen);
out_rawdata(&data, zero_buffer, align);
}
}
if (instruction->times > 1)
lfmt->downlevel(LIST_TIMES);
} else if (instruction->opcode == I_INCBIN) {
const char *fname = instruction->eops->stringval;
FILE *fp;
size_t t = instruction->times;
size_t t = instruction->times; /* INCBIN handles TIMES by itself */
off_t base = 0;
off_t len;
const void *map = NULL;
@ -700,7 +688,7 @@ int64_t assemble(int32_t segment, int64_t start, int bits, insn *instruction)
end_incbin:
lfmt->downlevel(LIST_INCBIN);
if (instruction->times > 1) {
lfmt->set_offset(data.offset);
lfmt->set_offset(start);
lfmt->uplevel(LIST_TIMES);
lfmt->downlevel(LIST_TIMES);
}
@ -716,6 +704,7 @@ int64_t assemble(int32_t segment, int64_t start, int bits, insn *instruction)
nasm_unmap_file(map, len);
fclose(fp);
done:
instruction->times = 1; /* Tell the upper layer not to iterate */
;
} else {
/* "Real" instruction */
@ -729,27 +718,15 @@ int64_t assemble(int32_t segment, int64_t start, int bits, insn *instruction)
/* Matches! */
int64_t insn_size = calcsize(data.segment, data.offset,
bits, instruction, temp);
itimes = instruction->times;
if (insn_size < 0) /* shouldn't be, on pass two */
nasm_panic(0, "errors made it through from pass one");
nasm_assert(insn_size >= 0);
data.itemp = temp;
data.bits = bits;
data.insoffs = 0;
data.inslen = insn_size;
while (itimes--) {
data.insoffs = 0;
data.inslen = insn_size;
gencode(&data, instruction);
nasm_assert(data.insoffs == insn_size);
if (itimes > 0 && itimes == instruction->times - 1) {
lfmt->set_offset(data.offset);
lfmt->uplevel(LIST_TIMES);
}
}
if (instruction->times > 1)
lfmt->downlevel(LIST_TIMES);
gencode(&data, instruction);
nasm_assert(data.insoffs == insn_size);
} else {
/* No match */
switch (m) {
@ -794,6 +771,8 @@ int64_t assemble(int32_t segment, int64_t start, int bits, insn *instruction)
"invalid combination of opcode and operands");
break;
}
instruction->times = 1; /* Avoid repeated error messages */
}
}
return data.offset - start;
@ -807,15 +786,13 @@ int64_t insn_size(int32_t segment, int64_t offset, int bits, insn *instruction)
if (instruction->opcode == I_none)
return 0;
if (instruction->opcode == I_DB || instruction->opcode == I_DW ||
instruction->opcode == I_DD || instruction->opcode == I_DQ ||
instruction->opcode == I_DT || instruction->opcode == I_DO ||
instruction->opcode == I_DY) {
if (opcode_is_db(instruction->opcode)) {
extop *e;
int32_t isize, osize, wsize;
isize = 0;
wsize = idata_bytes(instruction->opcode);
nasm_assert(wsize > 0);
list_for_each(e, instruction->eops) {
int32_t align;
@ -859,6 +836,9 @@ int64_t insn_size(int32_t segment, int64_t offset, int bits, insn *instruction)
}
}
len *= instruction->times;
instruction->times = 1; /* Tell the upper layer to not iterate */
return len;
}

View file

@ -222,9 +222,16 @@ static void list_output(const struct out_data *data)
break;
}
case OUT_ADDRESS:
case OUT_SEGMENT:
list_address(offset, "[]", data->toffset, size);
list_address(offset, "[]", data->toffset, size);
break;
case OUT_SEGMENT:
q[0] = '[';
memset(q+1, 's', size << 1);
q[(size << 1)+1] = ']';
q[(size << 1)+2] = '\0';
list_out(offset, q);
offset += size;
break;
case OUT_RELADDR:
list_address(offset, "()", data->toffset, size);
break;

View file

@ -1337,93 +1337,114 @@ static void assemble_file(char *fname, StrList **depend_ptr)
}
}
} else { /* instruction isn't an EQU */
int32_t n;
if (pass1 == 1) {
int64_t l = insn_size(location.segment, offs, globalbits,
&output_ins);
l *= output_ins.times;
nasm_assert(output_ins.times >= 0);
/* if (using_debug_info) && output_ins.opcode != -1) */
if (using_debug_info)
{ /* fbk 03/25/01 */
for (n = 1; n <= output_ins.times; n++) {
if (pass1 == 1) {
int64_t l = insn_size(location.segment, offs,
globalbits, &output_ins);
/* if (using_debug_info) && output_ins.opcode != -1) */
if (using_debug_info)
{ /* fbk 03/25/01 */
/* this is done here so we can do debug type info */
int32_t typeinfo =
TYS_ELEMENTS(output_ins.operands);
switch (output_ins.opcode) {
case I_RESB:
typeinfo =
TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_BYTE;
break;
case I_RESW:
typeinfo =
TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_WORD;
break;
case I_RESD:
typeinfo =
TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_DWORD;
break;
case I_RESQ:
typeinfo =
TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_QWORD;
break;
case I_REST:
typeinfo =
TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_TBYTE;
break;
case I_RESO:
typeinfo =
TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_OWORD;
break;
case I_RESY:
typeinfo =
TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_YWORD;
break;
case I_DB:
typeinfo |= TY_BYTE;
break;
case I_DW:
typeinfo |= TY_WORD;
break;
case I_DD:
if (output_ins.eops_float)
typeinfo |= TY_FLOAT;
else
typeinfo |= TY_DWORD;
break;
case I_DQ:
typeinfo |= TY_QWORD;
break;
case I_DT:
typeinfo |= TY_TBYTE;
break;
case I_DO:
typeinfo |= TY_OWORD;
break;
case I_DY:
typeinfo |= TY_YWORD;
break;
default:
typeinfo = TY_LABEL;
int32_t typeinfo =
TYS_ELEMENTS(output_ins.operands);
switch (output_ins.opcode) {
case I_RESB:
typeinfo =
TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_BYTE;
break;
case I_RESW:
typeinfo =
TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_WORD;
break;
case I_RESD:
typeinfo =
TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_DWORD;
break;
case I_RESQ:
typeinfo =
TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_QWORD;
break;
case I_REST:
typeinfo =
TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_TBYTE;
break;
case I_RESO:
typeinfo =
TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_OWORD;
break;
case I_RESY:
typeinfo =
TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_YWORD;
break;
case I_RESZ:
typeinfo =
TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_ZWORD;
break;
case I_DB:
typeinfo |= TY_BYTE;
break;
case I_DW:
typeinfo |= TY_WORD;
break;
case I_DD:
if (output_ins.eops_float)
typeinfo |= TY_FLOAT;
else
typeinfo |= TY_DWORD;
break;
case I_DQ:
typeinfo |= TY_QWORD;
break;
case I_DT:
typeinfo |= TY_TBYTE;
break;
case I_DO:
typeinfo |= TY_OWORD;
break;
case I_DY:
typeinfo |= TY_YWORD;
break;
case I_DZ:
typeinfo |= TY_ZWORD;
break;
default:
typeinfo = TY_LABEL;
break;
}
dfmt->debug_typevalue(typeinfo);
}
dfmt->debug_typevalue(typeinfo);
}
if (l != -1) {
offs += l;
/*
* For INCBIN, let the code in assemble
* handle TIMES, so we don't have to read the
* input file over and over.
*/
if (l != -1) {
offs += l;
set_curr_offs(offs);
}
/*
* else l == -1 => invalid instruction, which will be
* flagged as an error on pass 2
*/
} else {
if (n == 2)
lfmt->uplevel(LIST_TIMES);
offs += assemble(location.segment, offs,
globalbits, &output_ins);
set_curr_offs(offs);
}
/*
* else l == -1 => invalid instruction, which will be
* flagged as an error on pass 2
*/
} /* not an EQU */
}
if (output_ins.times > 1)
lfmt->downlevel(LIST_TIMES);
} else {
offs += assemble(location.segment, offs, globalbits, &output_ins);
set_curr_offs(offs);
}
} /* not an EQU */
cleanup_insn(&output_ins);
end_of_line:

View file

@ -444,6 +444,9 @@ restart_parse:
stdscan_set(buffer);
i = stdscan(NULL, &tokval);
nasm_static_assert(P_none == 0);
memset(result->prefixes, P_none, sizeof(result->prefixes));
result->times = 1; /* No TIMES either yet */
result->label = NULL; /* Assume no label */
result->eops = NULL; /* must do this, whatever happens */
result->operands = 0; /* must initialize this */
@ -491,10 +494,6 @@ restart_parse:
if (i == TOKEN_EOS)
goto fail;
nasm_static_assert(P_none == 0);
memset(result->prefixes, P_none, sizeof(result->prefixes));
result->times = 1L;
while (i == TOKEN_PREFIX ||
(i == TOKEN_REG && IS_SREG(tokval.t_integer))) {
first = false;
@ -581,11 +580,7 @@ restart_parse:
} else
critical = (pass == 2 ? 2 : 0);
if (result->opcode == I_DB || result->opcode == I_DW ||
result->opcode == I_DD || result->opcode == I_DQ ||
result->opcode == I_DT || result->opcode == I_DO ||
result->opcode == I_DY || result->opcode == I_DZ ||
result->opcode == I_INCBIN) {
if (opcode_is_db(result->opcode) || result->opcode == I_INCBIN) {
extop *eop, **tail = &result->eops, **fixptr;
int oper_num = 0;
int32_t sign;
@ -1133,37 +1128,11 @@ is_expression:
/*
* Transform RESW, RESD, RESQ, REST, RESO, RESY, RESZ into RESB.
*/
switch (result->opcode) {
case I_RESW:
if (opcode_is_resb(result->opcode)) {
result->oprs[0].offset *= resv_bytes(result->opcode);
result->oprs[0].offset *= result->times;
result->times = 1;
result->opcode = I_RESB;
result->oprs[0].offset *= 2;
break;
case I_RESD:
result->opcode = I_RESB;
result->oprs[0].offset *= 4;
break;
case I_RESQ:
result->opcode = I_RESB;
result->oprs[0].offset *= 8;
break;
case I_REST:
result->opcode = I_RESB;
result->oprs[0].offset *= 10;
break;
case I_RESO:
result->opcode = I_RESB;
result->oprs[0].offset *= 16;
break;
case I_RESY:
result->opcode = I_RESB;
result->oprs[0].offset *= 32;
break;
case I_RESZ:
result->opcode = I_RESB;
result->oprs[0].offset *= 64;
break;
default:
break;
}
return result;

View file

@ -91,3 +91,32 @@ int idata_bytes(int opcode)
return 0;
}
}
/*
* Uninitialized data bytes length from opcode
*/
int resv_bytes(int opcode)
{
switch (opcode) {
case I_RESB:
return 1;
case I_RESW:
return 2;
case I_RESD:
return 4;
case I_RESQ:
return 8;
case I_REST:
return 10;
case I_RESO:
return 16;
case I_RESY:
return 32;
case I_RESZ:
return 64;
case I_none:
return -1;
default:
return 0;
}
}

View file

@ -7,6 +7,20 @@
The NASM 2 series supports x86-64, and is the production version of NASM
since 2007.
\S{cl-2.13.01} Version 2.13.01
\b Fix incorrect output for some types of \c{FAR} or \c{SEG}
references in the \c{obj} output format, and possibly other 16-bit
output formats.
\b Fix the address in the list file for an instruction containing a
\c{TIMES} directive.
\b Fix error with \c{TIMES} used together with an instruction which
can vary in size, e.g. \c{JMP}.
\b Fix breakage on some uses of the \c{DZ} pseudo-op.
\S{cl-2.13} Version 2.13
\b Support the official forms of the \c{UD0} and \c{UD1} instructions.

View file

@ -48,4 +48,23 @@ extern const uint8_t nasm_bytecodes[];
*/
#define ITEMPLATE_END {-1,-1,{-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1},NULL,0}
/* Width of Dx and RESx instructions */
int const_func idata_bytes(enum opcode opcode);
int const_func resv_bytes(enum opcode opcode);
/*
* Pseudo-op tests
*/
/* DB-type instruction (DB, DW, ...) */
static inline bool opcode_is_db(enum opcode opcode)
{
return idata_bytes(opcode) > 0;
}
/* RESB-type instruction (RESB, RESW, ...) */
static inline bool opcode_is_resb(enum opcode opcode)
{
return resv_bytes(opcode) > 0;
}
#endif /* NASM_INSNS_H */

View file

@ -1053,6 +1053,7 @@ extern const struct dfmt *dfmt;
#define TY_TBYTE 0x38
#define TY_OWORD 0x40
#define TY_YWORD 0x48
#define TY_ZWORD 0x50
#define TY_COMMON 0xE0
#define TY_SEG 0xE8
#define TY_EXTERN 0xF0

View file

@ -410,8 +410,6 @@ static inline int64_t const_func signed_bits(int64_t value, int bits)
return value;
}
int const_func idata_bytes(int opcode);
/* check if value is power of 2 */
#define is_power2(v) ((v) && ((v) & ((v) - 1)) == 0)

View file

@ -282,6 +282,9 @@ static void cv8_typevalue(int32_t type)
case TY_YWORD:
cv8_state.last_sym->symtype = TYPE_REAL256;
break;
case TY_ZWORD:
cv8_state.last_sym->symtype = TYPE_REAL512;
break;
case TY_UNKNOWN:
break;
case TY_LABEL:

View file

@ -89,7 +89,9 @@ void nasm_do_legacy_output(const struct out_data *data)
case OUT_SEGMENT:
type = OUT_ADDRESS;
/* fall through */
dptr = &zero_buffer;
size = (data->sign == OUT_SIGNED) ? -data->size : data->size;
break;
case OUT_ADDRESS:
dptr = &data->toffset;

View file

@ -2460,6 +2460,10 @@ static void debug_typevalue(int32_t type)
ssize = 32;
stype = STT_OBJECT;
break;
case TY_ZWORD:
ssize = 64;
stype = STT_OBJECT;
break;
case TY_COMMON:
ssize = 0;
stype = STT_COMMON;

View file

@ -28,6 +28,9 @@ $(NASM):
%.obj: %.asm $(NASM)
$(NASM) $(NASMOPT) -f obj -o $@ -l $*.lst $<
%.od: %.obj ../misc/omfdump
../misc/omfdump $< > $@
%.coff: %.asm $(NASM)
$(NASM) $(NASMOPT) -f coff -o $@ -l $*.lst $<

View file

@ -4,3 +4,4 @@
section more start=0x1000000
db '*** TWELVE ***', 0Ah
times 12 incbin "incbin.data",32
db '<END>', 0Ah

View file

@ -6,3 +6,16 @@
; Broken per BR 3392279
bswap r12d
times 4 bswap r12d
; Forward jump
times 128 jmp there
there:
nop
; Backwards jump
times 128 jmp there
section .bss
times 0x10 resb 0x20
resb 1