diff options
-rw-r--r-- | asm/assemble.c | 151 | ||||
-rw-r--r-- | asm/nasm.c | 234 |
2 files changed, 209 insertions, 176 deletions
diff --git a/asm/assemble.c b/asm/assemble.c index 42509ec6..115eea22 100644 --- a/asm/assemble.c +++ b/asm/assemble.c @@ -823,19 +823,133 @@ int64_t assemble(int32_t segment, int64_t start, int bits, insn *instruction) return data.offset - start; } +static void debug_set_db_type(insn *instruction) +{ + /* Is this really correct? .operands doesn't mean much for Dx */ + int32_t typeinfo = TYS_ELEMENTS(instruction->operands); + + switch (instruction->opcode) { + case I_DB: + typeinfo |= TY_BYTE; + break; + case I_DW: + typeinfo |= TY_WORD; + break; + case I_DD: + if (instruction->eops_float) + typeinfo |= TY_FLOAT; + else + typeinfo |= TY_DWORD; + break; + case I_DQ: + /* What about double? */ + typeinfo |= TY_QWORD; + break; + case I_DT: + /* What about long double? */ + 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: + panic(); + } + + dfmt->debug_typevalue(typeinfo); +} + +static void debug_set_type(insn *instruction) +{ + int32_t typeinfo; + + if (opcode_is_resb(instruction->opcode)) { + typeinfo = TYS_ELEMENTS(instruction->oprs[0].offset); + + switch (instruction->opcode) { + case I_RESB: + typeinfo |= TY_BYTE; + break; + case I_RESW: + typeinfo |= TY_WORD; + break; + case I_RESD: + typeinfo |= TY_DWORD; + break; + case I_RESQ: + typeinfo |= TY_QWORD; + break; + case I_REST: + typeinfo |= TY_TBYTE; + break; + case I_RESO: + typeinfo |= TY_OWORD; + break; + case I_RESY: + typeinfo |= TY_YWORD; + break; + case I_RESZ: + typeinfo |= TY_ZWORD; + break; + default: + panic(); + } + } else { + typeinfo = TY_LABEL; + } + + dfmt->debug_typevalue(typeinfo); +} + + +/* Proecess an EQU directive */ +static void define_equ(insn * instruction) +{ + if (!instruction->label) { + nasm_nonfatal("EQU not preceded by label"); + } else if (instruction->operands == 1 && + (instruction->oprs[0].type & IMMEDIATE) && + instruction->oprs[0].wrt == NO_SEG) { + define_label(instruction->label, + instruction->oprs[0].segment, + instruction->oprs[0].offset, false); + } else if (instruction->operands == 2 + && (instruction->oprs[0].type & IMMEDIATE) + && (instruction->oprs[0].type & COLON) + && instruction->oprs[0].segment == NO_SEG + && instruction->oprs[0].wrt == NO_SEG + && (instruction->oprs[1].type & IMMEDIATE) + && instruction->oprs[1].segment == NO_SEG + && instruction->oprs[1].wrt == NO_SEG) { + define_label(instruction->label, + instruction->oprs[0].offset | SEG_ABS, + instruction->oprs[1].offset, false); + } else { + nasm_nonfatal("bad syntax for EQU"); + } +} + int64_t insn_size(int32_t segment, int64_t offset, int bits, insn *instruction) { const struct itemplate *temp; enum match_result m; + int64_t isize = 0; - if (instruction->opcode == I_none) + if (instruction->opcode == I_none) { return 0; - - if (opcode_is_db(instruction->opcode)) { + } else if (instruction->opcode == I_EQU) { + define_equ(instruction); + return 0; + } else if (opcode_is_db(instruction->opcode)) { extop *e; - int32_t isize, osize, wsize; + int32_t osize, wsize; - isize = 0; wsize = db_bytes(instruction->opcode); nasm_assert(wsize > 0); @@ -855,10 +969,10 @@ int64_t insn_size(int32_t segment, int64_t offset, int bits, insn *instruction) align += wsize; isize += osize + align; } - return isize; - } - if (instruction->opcode == I_INCBIN) { + debug_set_db_type(instruction); + return isize; + } else if (instruction->opcode == I_INCBIN) { const char *fname = instruction->eops->stringval; off_t len; @@ -885,17 +999,20 @@ int64_t insn_size(int32_t segment, int64_t offset, int bits, insn *instruction) instruction->times = 1; /* Tell the upper layer to not iterate */ return len; - } + } else { + /* Normal instruction, or RESx */ - /* Check to see if we need an address-size prefix */ - add_asp(instruction, bits); + /* Check to see if we need an address-size prefix */ + add_asp(instruction, bits); - m = find_match(&temp, instruction, segment, offset, bits); - if (m == MOK_GOOD) { - /* we've matched an instruction. */ - return calcsize(segment, offset, bits, instruction, temp); - } else { - return -1; /* didn't match any instruction */ + m = find_match(&temp, instruction, segment, offset, bits); + if (m != MOK_GOOD) + return -1; /* No match */ + + isize = calcsize(segment, offset, bits, instruction, temp); + debug_set_type(instruction); + + return isize; } } @@ -1410,11 +1410,83 @@ static void parse_cmdline(int argc, char **argv, int pass) } } +static void forward_refs(insn *instruction) +{ + int i; + struct forwrefinfo *fwinf; + + instruction->forw_ref = false; + + if (!optimizing.level) + return; /* For -O0 don't bother */ + + if (!forwref) + return; + + if (forwref->lineno != globallineno) + return; + + instruction->forw_ref = true; + do { + instruction->oprs[forwref->operand].opflags |= OPFLAG_FORWARD; + forwref = saa_rstruct(forwrefs); + } while (forwref && forwref->lineno == globallineno); + + if (!pass_first()) + return; + + for (i = 0; i < instruction->operands; i++) { + if (instruction->oprs[i].opflags & OPFLAG_FORWARD) { + fwinf = saa_wstruct(forwrefs); + fwinf->lineno = globallineno; + fwinf->operand = i; + } + } +} + +static void process_insn(insn *instruction) +{ + int32_t n; + int64_t l; + + if (!instruction->times) + return; /* Nothing to do... */ + + nasm_assert(instruction->times > 0); + + /* + * NOTE: insn_size() can change instruction->times + * (usually to 1) when called. + */ + if (!pass_final()) { + for (n = 1; n <= instruction->times; n++) { + l = insn_size(location.segment, location.offset, + globalbits, instruction); + if (l != -1) /* l == -1 -> invalid instruction */ + increment_offset(l); + } + } else { + l = assemble(location.segment, location.offset, + globalbits, instruction); + /* We can't get an invalid instruction here */ + increment_offset(l); + + if (instruction->times > 1) { + lfmt->uplevel(LIST_TIMES); + for (n = 2; n <= instruction->times; n++) { + l = assemble(location.segment, location.offset, + globalbits, instruction); + increment_offset(l); + } + lfmt->downlevel(LIST_TIMES); + } + } +} + static void assemble_file(const char *fname, struct strlist *depend_list) { char *line; insn output_ins; - int i; uint64_t prev_offset_changed; int64_t stall_count = 0; /* Make sure we make forward progress... */ @@ -1498,164 +1570,8 @@ static void assemble_file(const char *fname, struct strlist *depend_list) /* Not a directive, or even something that starts with [ */ parse_line(line, &output_ins); - - if (optimizing.level > 0) { - if (forwref != NULL && globallineno == forwref->lineno) { - output_ins.forw_ref = true; - do { - output_ins.oprs[forwref->operand].opflags |= OPFLAG_FORWARD; - forwref = saa_rstruct(forwrefs); - } while (forwref != NULL - && forwref->lineno == globallineno); - } else - output_ins.forw_ref = false; - - if (output_ins.forw_ref) { - if (pass_first()) { - for (i = 0; i < output_ins.operands; i++) { - if (output_ins.oprs[i].opflags & OPFLAG_FORWARD) { - struct forwrefinfo *fwinf = (struct forwrefinfo *)saa_wstruct(forwrefs); - fwinf->lineno = globallineno; - fwinf->operand = i; - } - } - } - } - } - - /* forw_ref */ - if (output_ins.opcode == I_EQU) { - if (!output_ins.label) { - nasm_nonfatal("EQU not preceded by label"); - } else if (output_ins.operands == 1 && - (output_ins.oprs[0].type & IMMEDIATE) && - output_ins.oprs[0].wrt == NO_SEG) { - define_label(output_ins.label, - output_ins.oprs[0].segment, - output_ins.oprs[0].offset, false); - } else if (output_ins.operands == 2 - && (output_ins.oprs[0].type & IMMEDIATE) - && (output_ins.oprs[0].type & COLON) - && output_ins.oprs[0].segment == NO_SEG - && output_ins.oprs[0].wrt == NO_SEG - && (output_ins.oprs[1].type & IMMEDIATE) - && output_ins.oprs[1].segment == NO_SEG - && output_ins.oprs[1].wrt == NO_SEG) { - define_label(output_ins.label, - output_ins.oprs[0].offset | SEG_ABS, - output_ins.oprs[1].offset, false); - } else { - nasm_nonfatal("bad syntax for EQU"); - } - } else { /* instruction isn't an EQU */ - int32_t n; - - nasm_assert(output_ins.times >= 0); - - for (n = 1; n <= output_ins.times; n++) { - if (!pass_final()) { - int64_t l = insn_size(location.segment, - location.offset, - 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_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); - } - - /* - * 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) { - increment_offset(l); - } - /* - * else l == -1 => invalid instruction, which will be - * flagged as an error on pass 2 - */ - } else { - if (n == 2) - lfmt->uplevel(LIST_TIMES); - increment_offset(assemble(location.segment, - location.offset, - globalbits, &output_ins)); - } - } /* not an EQU */ - } - if (output_ins.times > 1) - lfmt->downlevel(LIST_TIMES); - + forward_refs(&output_ins); + process_insn(&output_ins); cleanup_insn(&output_ins); end_of_line: |