From 5d9f0ecf62f6d8503f847bbe73bbe009d53c9e0e Mon Sep 17 00:00:00 2001 From: Steve Chamberlain Date: Tue, 21 Jan 1992 22:14:16 +0000 Subject: * as.c: change -l to -a[lsn], to avoid conflict with 68000 command line option. * listing.h, listing.c: now prints addresses with ??? instead of 0 when errors in assemble prevent addresses being known. Prints symbol table more tidily. Allows different parts of the listing to be selected. --- gas/as.c | 105 +++-- gas/config/ho-sunos.h | 6 +- gas/config/tc-h8300.c | 1187 +++++++++++++++++++++++++++++++++---------------- gas/listing.c | 821 ++++++++++++++++++++++++++++++++++ gas/listing.h | 20 + 5 files changed, 1727 insertions(+), 412 deletions(-) create mode 100644 gas/listing.c create mode 100644 gas/listing.h diff --git a/gas/as.c b/gas/as.c index a885f0d..c975766 100644 --- a/gas/as.c +++ b/gas/as.c @@ -5,7 +5,7 @@ This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 1, or (at your option) +the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, @@ -45,7 +45,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define COMMON #include "as.h" - +#include "subsegs.h" #ifdef __STDC__ /* This prototype for got_sig() is ansi. If you want @@ -77,6 +77,8 @@ static char * gdb_symbol_file_name; long gdb_begin(); #endif +int listing; /* true if a listing is wanted */ + char *myname; /* argv[0] */ extern char version_string[]; @@ -139,10 +141,42 @@ char **argv; while ((a = * arg) != '\0') {/* scan all the 1-char flags */ arg ++; /* arg->after letter. */ a &= 0x7F; /* ascii only please */ - if (flagseen[a]) - as_tsktsk("%s: Flag option - %c has already been seen.", myname, a); + /* if (flagseen[a]) + as_tsktsk("%s: Flag option - %c has already been seen.", myname, a); */ flagseen[a] = 1; switch (a) { + + case 'a': + { + int loop =1; + + while (loop) { + switch (*arg) + { + case 'l': + listing |= LISTING_LISTING; + arg++; + break; + case 's': + listing |= LISTING_SYMBOLS; + arg++; + break; + case 'n': + listing |= LISTING_NOFORM; + arg++; + break; + default: + if (!listing) + listing= LISTING_DEFAULT; + loop = 0; + break; + } + } + } + + break; + + case 'f': break; /* -f means fast - no need for "app" preprocessor. */ @@ -167,7 +201,7 @@ char **argv; case 'I': { /* Include file directory */ - char *temp; + char *temp = NULL; if (*arg) temp = stralloc (arg); else if (work_argc) { @@ -264,6 +298,10 @@ char **argv; input_scrub_end(); md_end(); /* MACHINE.c */ +#ifndef NO_LISTING + listing_print(); +#endif + #ifndef VMS return((had_warnings() && flagseen['Z']) || had_errors() > 0); /* WIN */ @@ -290,26 +328,43 @@ static void perform_an_assembly_pass(argc, argv) int argc; char **argv; { - int saw_a_file = 0; - - text_fix_root = NULL; - data_fix_root = NULL; - need_pass_2 = 0; - - subseg_new (SEG_TEXT, 0); - - argv++; /* skip argv[0] */ - argc--; /* skip argv[0] */ - while (argc--) { - if (*argv) { /* Is it a file-name argument? */ - saw_a_file++; - /* argv->"" if stdin desired, else->filename */ - read_a_source_file(*argv); - } - argv++; /* completed that argv */ - } - if(!saw_a_file) - read_a_source_file(""); + int saw_a_file = 0; + unsigned int i; + need_pass_2 = 0; + +#ifdef MANY_SEGMENTS + + for (i= SEG_E0; i < SEG_UNKNOWN; i++) + { + segment_info[i].fix_root = 0; + } + /* Create the three fixed ones */ + subseg_new (SEG_E0, 0); + subseg_new (SEG_E1, 0); + subseg_new (SEG_E2, 0); + strcpy(segment_info[SEG_E0].scnhdr.s_name,".text"); + strcpy(segment_info[SEG_E1].scnhdr.s_name,".data"); + strcpy(segment_info[SEG_E2].scnhdr.s_name,".bss"); + + subseg_new (SEG_E0, 0); +#else + text_fix_root = NULL; + data_fix_root = NULL; + + subseg_new (SEG_TEXT, 0); +#endif + argv++; /* skip argv[0] */ + argc--; /* skip argv[0] */ + while (argc--) { + if (*argv) { /* Is it a file-name argument? */ + saw_a_file++; + /* argv->"" if stdin desired, else->filename */ + read_a_source_file(*argv); + } + argv++; /* completed that argv */ + } + if(!saw_a_file) + read_a_source_file(""); } /* perform_an_assembly_pass() */ /* diff --git a/gas/config/ho-sunos.h b/gas/config/ho-sunos.h index 81c067c..1802632 100644 --- a/gas/config/ho-sunos.h +++ b/gas/config/ho-sunos.h @@ -9,7 +9,7 @@ #else extern int memset(); #endif - +#include #include #include @@ -21,11 +21,11 @@ extern char *realloc(); extern char *strrchr(); extern int _filbuf(); extern int _flsbuf(); -extern int abort(); +/*extern int abort();*/ extern int bcopy(); extern int bzero(); extern int bzero(); -extern int exit(); +/*extern int exit();*/ extern int fclose(); extern int fprintf(); extern int fread(); diff --git a/gas/config/tc-h8300.c b/gas/config/tc-h8300.c index 9008cac..735024b 100644 --- a/gas/config/tc-h8300.c +++ b/gas/config/tc-h8300.c @@ -20,30 +20,31 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Written By Steve Chamberlain - - steve@cygnus.com + sac@cygnus.com */ #include #include "as.h" #include "bfd.h" -#include "h8300-opcode.h" +#include "opcode/h8300.h" #include +#include "listing.h" char comment_chars[] = { ';',0 }; char line_separator_chars[] = { '$' ,0}; /* This table describes all the machine specific pseudo-ops the assembler has to support. The fields are: - pseudo-op name without dot - function to call to execute this pseudo-op - Integer arg to pass to the function + pseudo-op name without dot + function to call to execute this pseudo-op + Integer arg to pass to the function */ void cons(); + const pseudo_typeS md_pseudo_table[] = { { "int", cons, 2 }, - { 0, 0, 0 } + { 0,0,0 } }; int md_reloc_size ; @@ -60,7 +61,6 @@ const relax_typeS md_relax_table[1]; static struct hash_control *opcode_hash_control; /* Opcode mnemonics */ -static struct hash_control *register_hash_control; /* Register name hash table */ /* @@ -68,29 +68,106 @@ static struct hash_control *register_hash_control; /* Register name hash table * set up all the tables, etc that the MD part of the assembler needs */ -reloc_howto_type *r16; -reloc_howto_type *r8; -reloc_howto_type *r8ff; -reloc_howto_type *r8pcrel; +/* encode the size and number into the number field + xxnnnn + 00 8 bit + 01 16 bit + 10 ccr + nnnnreg number +*/ +#define WORD_REG 0x10 +#define BYTE_REG 0x00 +#define CCR_REG 0x20 + struct reg_entry +{ + char *name; + char number; +}; + +struct reg_entry reg_list[] = { +"r0",WORD_REG +0, +"r1",WORD_REG +1, +"r2",WORD_REG +2, +"r3",WORD_REG +3, +"r4",WORD_REG +4, +"r5",WORD_REG +5, +"r6",WORD_REG +6, +"r7",WORD_REG +7, +"fp",WORD_REG +6, +"sp",WORD_REG +7, +"r0h",BYTE_REG + 0, +"r0l",BYTE_REG + 1, +"r1h",BYTE_REG + 2, +"r1l",BYTE_REG + 3, +"r2h",BYTE_REG + 4, +"r2l",BYTE_REG + 5, +"r3h",BYTE_REG + 6, +"r3l",BYTE_REG + 7, +"r4h",BYTE_REG + 8, +"r4l",BYTE_REG + 9, +"r5h",BYTE_REG + 10, +"r5l",BYTE_REG + 11, +"r6h",BYTE_REG + 12, +"r6l",BYTE_REG + 13, +"r7h",BYTE_REG + 14, +"r7l",BYTE_REG + 15, +"ccr",CCR_REG, +0,0 +} +; + + + + void md_begin () { - bfd_arch_info_type *ai; - const struct h8_opcode *opcode; - + struct h8_opcode *opcode; + const struct reg_entry *reg; + char prev_buffer[100]; + int idx = 0; + opcode_hash_control = hash_new(); - for (opcode = h8_opcodes; opcode->name; opcode++) { - hash_insert(opcode_hash_control, opcode->name, (char *)opcode); - } - - ai = bfd_lookup_arch(bfd_arch_h8300,0); + prev_buffer[0] = 0; - r16 = ai->reloc_type_lookup(ai, BFD_RELOC_16); - r8 = ai->reloc_type_lookup(ai, BFD_RELOC_8); - r8ff = ai->reloc_type_lookup(ai, BFD_RELOC_8_FFnn); - r8pcrel = ai->reloc_type_lookup(ai, BFD_RELOC_8_PCREL); + for (opcode = h8_opcodes; opcode->name; opcode++) + { + /* Strip off any . part when inserting the opcode and only enter + unique codes into the hash table + */ + char *src= opcode->name; + unsigned int len = strlen(src); + char *dst = malloc(len+1); + char *buffer = dst; + opcode->size = 0; + while (*src) { + if (*src == '.') { + *dst++ = 0; + src++; + opcode->size = *src; + break; + } + *dst++ = *src++; + } + if (strcmp(buffer, prev_buffer)) + { + hash_insert(opcode_hash_control, buffer, (char *)opcode); + strcpy(prev_buffer, buffer); + idx++; + } + opcode->idx = idx; + + + /* Find the number of operands */ + opcode->noperands = 0; + while (opcode->args.nib[opcode->noperands] != E) + opcode->noperands ++; + /* Find the length of the opcode in bytes */ + opcode->length =0; + while (opcode->data.nib[opcode->length*2] != E) + opcode->length++; + } - } @@ -101,9 +178,10 @@ struct h8_exp { }; struct h8_op { -op_type mode; - unsigned reg; - expressionS exp; + unsigned int dispreg; + op_type mode; + unsigned reg; + expressionS exp; }; @@ -124,46 +202,55 @@ op_type r16_sord[] = {RS16, RD16}; op_type rind_sord[] = {RSIND, RDIND}; op_type abs_sord[2] = {ABS16SRC, ABS16DST}; op_type disp_sord[] = {DISPSRC, DISPDST}; + /* try and parse a reg name, returns number of chars consumed */ -int DEFUN(parse_reg,(src, mode, reg, dst), - char *src AND - op_type *mode AND - unsigned int *reg AND - int dst) +int +DEFUN(parse_reg,(src, mode, reg, dst), + char *src AND + op_type *mode AND + unsigned int *reg AND + int dst) { - if (src[0] == 's' && src[1] == 'p') { - *mode = r16_sord[dst]; - *reg = 7; - return 2; - } - if (src[0] == 'c' && src[1] == 'c' && src[2] == 'r') { - *mode = CCR; - *reg = 0; - return 3; - } - if (src[0] == 'f' && src[1] == 'p') { - *mode = r16_sord[dst]; - *reg = 6; - return 2; - } - if (src[0] == 'r') { - if (src[1] >= '0' && src[1] <= '7') { - if(src[2] == 'l') { - *mode = r8_sord[dst]; - *reg = (src[1] - '0') + 8; - return 3; - } - if(src[2] == 'h') { - *mode = r8_sord[dst]; - *reg = (src[1] - '0') ; + if (src[0] == 's' && src[1] == 'p') + { + *mode = r16_sord[dst]; + *reg = 7; + return 2; + } + if (src[0] == 'c' && src[1] == 'c' && src[2] == 'r') + { + *mode = CCR; + *reg = 0; return 3; - } - *mode = r16_sord[dst]; - *reg = (src[1] - '0'); - return 2; } - } - return 0; + if (src[0] == 'f' && src[1] == 'p') + { + *mode = r16_sord[dst]; + *reg = 6; + return 2; + } + if (src[0] == 'r') + { + if (src[1] >= '0' && src[1] <= '7') + { + if(src[2] == 'l') + { + *mode = r8_sord[dst]; + *reg = (src[1] - '0') + 8; + return 3; + } + if(src[2] == 'h') + { + *mode = r8_sord[dst]; + *reg = (src[1] - '0') ; + return 3; + } + *mode = r16_sord[dst]; + *reg = (src[1] - '0'); + return 2; + } + } + return 0; } char * @@ -179,23 +266,52 @@ DEFUN(parse_exp,(s, op), new = input_line_pointer; input_line_pointer = save; if (SEG_NORMAL(seg)) - return new; + return new; switch (seg) { - case SEG_ABSOLUTE: - case SEG_UNKNOWN: - case SEG_DIFFERENCE: - case SEG_BIG: - case SEG_REGISTER: - return new; - case SEG_ABSENT: - as_bad("Missing operand"); - return new; - default: - as_bad("Don't understand operand of type %s", segment_name (seg)); - return new; - } + case SEG_ABSOLUTE: + case SEG_UNKNOWN: + case SEG_DIFFERENCE: + case SEG_BIG: + case SEG_REGISTER: + return new; + case SEG_ABSENT: + as_bad("Missing operand"); + return new; + default: + as_bad("Don't understand operand of type %s", segment_name (seg)); + return new; + } +} + +static char * +DEFUN(skip_colonthing,(ptr), + char *ptr) +{ + if (*ptr == ':') { + ptr++; + while (isdigit(*ptr)) + ptr++; + + } + return ptr; } +/* The many forms of operand: + + Rn Register direct + @Rn Register indirect + @(exp[:16], Rn) Register indirect with displacement + @Rn+ + @-Rn + @aa:8 absolute 8 bit + @aa:16 absolute 16 bit + @aa absolute 16 bit + + #xx[:size] immediate data + @(exp:[8], pc) pc rel + @@aa[:8] memory indirect + +*/ static void DEFUN(get_operand,(ptr, op, dst), @@ -207,21 +323,38 @@ DEFUN(get_operand,(ptr, op, dst), op_type mode; unsigned int num; unsigned int len; + unsigned int size; op->mode = E; - while (*src == ' ') src++; len = parse_reg(src, &op->mode, &op->reg, dst); if (len) { - *ptr = src + len; - return ; - } + *ptr = src + len; + return ; + } - if (*src == '@') { + if (*src == '@') + { src++; - if (*src == '-') { + if (*src == '@') + { + src++; + src = parse_exp(src,&op->exp); + src = skip_colonthing(src); + + *ptr = src; + + op->mode = MEMIND; + return; + + } + + + if (*src == '-') + { src++; len = parse_reg(src, &mode, &num, dst); - if (len == 0 || mode != r16_sord[dst]) { + if (len == 0 || mode != r16_sord[dst]) + { as_bad("@- needs word register"); } op->mode = RDDEC; @@ -229,29 +362,37 @@ DEFUN(get_operand,(ptr, op, dst), *ptr = src + len; return; } - if (*src == '(' && ')') { + if (*src == '(' && ')') + { /* Disp */ src++; src = parse_exp(src, &op->exp); - if (*src == ')') { + if (*src == ')') + { src++; op->mode = abs_sord[dst]; *ptr = src; return; } - if (*src != ',') { + src = skip_colonthing(src); + + if (*src != ',') + { as_bad("expected @(exp, reg16)"); } src++; len = parse_reg(src, &mode, &op->reg, dst); if (len == 0 || mode != r16_sord[dst]) - { - as_bad("expected @(exp, reg16)"); - } + { + as_bad("expected @(exp, reg16)"); + } op->mode = disp_sord[dst]; src += len; - if (*src != ')' && '(') { + src = skip_colonthing(src); + + if (*src != ')' && '(') + { as_bad("expected @(exp, reg16)"); } @@ -262,46 +403,492 @@ DEFUN(get_operand,(ptr, op, dst), len = parse_reg(src, &mode, &num, dst); if(len) { - src += len; - if (*src == '+') { - src++; - if (mode != RS16) { - as_bad("@Rn+ needs word register"); + src += len; + if (*src == '+') + { + src++; + if (mode != RS16) + { + as_bad("@Rn+ needs src word register"); + } + op->mode = RSINC; + op->reg = num; + *ptr = src; + return; + } + if (mode != r16_sord[dst]) + { + as_bad("@Rn needs word register"); } - op->mode = RSINC; + op->mode =rind_sord[dst]; op->reg = num; *ptr = src; return; } - if (mode != r16_sord[dst]) { - as_bad("@Rn needs word register"); - } - op->mode =rind_sord[dst]; - op->reg = num; - *ptr = src; - return; - } - else { + else + { /* must be a symbol */ op->mode = abs_sord[dst]; - *ptr = parse_exp(src, &op->exp); + *ptr = skip_colonthing(parse_exp(src, &op->exp)); + return; } } if (*src == '#') { - src++; - op->mode = IMM16; - *ptr = parse_exp(src, &op->exp); - return; - } + src++; + op->mode = IMM16; + src = parse_exp(src, &op->exp); + *ptr= skip_colonthing(src); + + return; + } else { - *ptr = parse_exp(src, &op->exp); - op->mode = DISP8; + *ptr = parse_exp(src, &op->exp); + op->mode = DISP8; + } +} + + +static +char * +DEFUN(get_operands,(noperands,op_end, operand), + unsigned int noperands AND + char *op_end AND + struct h8_op *operand) +{ + char *ptr = op_end; + switch (noperands) + { + case 0: + operand[0].mode = 0; + operand[1].mode = 0; + break; + + case 1: + ptr++; + get_operand(& ptr, operand +0,0); + operand[1].mode =0; + break; + + case 2: + ptr++; + get_operand(& ptr, operand +0,0); + if (*ptr == ',') ptr++; + get_operand(& ptr, operand +1, 1); + break; + + default: + abort(); } + + + return ptr; } +/* Passed a pointer to a list of opcodes which use different + addressing modes, return the opcode which matches the opcodes + provided + */ +static +struct h8_opcode * +DEFUN(get_specific,(opcode, operands), + struct h8_opcode *opcode AND + struct h8_op *operands) + +{ + struct h8_opcode *this_try = opcode ; + int found = 0; + unsigned int noperands = opcode->noperands; + + unsigned int dispreg; + unsigned int this_index = opcode->idx; + while (this_index == opcode->idx && !found) + { + unsigned int i; + + this_try = opcode ++; + for (i = 0; i < noperands; i++) + { + op_type op = (this_try->args.nib[i]) & ~(B30|B31); + switch (op) + { + case Hex0: + case Hex1: + case Hex2: + case Hex3: + case Hex4: + case Hex5: + case Hex6: + case Hex7: + case Hex8: + case Hex9: + case HexA: + case HexB: + case HexC: + case HexD: + case HexE: + case HexF: + break; + case DISPSRC: + case DISPDST: + operands[0].dispreg = operands[i].reg; + case RD8: + case RS8: + case RDIND: + case RSIND: + case RD16: + case RS16: + case CCR: + case RSINC: + case RDDEC: + if (operands[i].mode != op) goto fail; + break; + case KBIT: + case IMM16: + case IMM3: + case IMM8: + if (operands[i].mode != IMM16) goto fail; + break; + case MEMIND: + if (operands[i].mode != MEMIND) goto fail; + break; + case ABS16SRC: + case ABS8SRC: + case ABS16OR8SRC: + case ABS16ORREL8SRC: + + if (operands[i].mode != ABS16SRC) goto fail; + break; + case ABS16OR8DST: + case ABS16DST: + case ABS8DST: + if (operands[i].mode != ABS16DST) goto fail; + break; + } + } + found =1; + fail: ; + } + if (found) + return this_try; + else + return 0; +} + +static void +DEFUN(check_operand,(operand, width, string), + struct h8_op *operand AND + unsigned int width AND + char *string) +{ + if (operand->exp.X_add_symbol == 0 + && operand->exp.X_subtract_symbol == 0) + { + + /* No symbol involved, let's look at offset, it's dangerous if any of + the high bits are not 0 or ff's, find out by oring or anding with + the width and seeing if the answer is 0 or all fs*/ + if ((operand->exp.X_add_number | width) != ~0 && + (operand->exp.X_add_number & ~width)!= 0) + { + as_warn("operand %s0x%x out of range.", string, operand->exp.X_add_number); + } + } + +} + +/* Now we know what sort of opcodes it is, lets build the bytes - + */ +static void +DEFUN (build_bytes,(this_try, operand), + struct h8_opcode *this_try AND + struct h8_op *operand) + +{ + unsigned int i; + + char *output = frag_more(this_try->length); + char *output_ptr = output; + op_type *nibble_ptr = this_try->data.nib; + char part; + op_type c; + char high; + int nib; + top: ; + while (*nibble_ptr != E) + { + int nibble; + for (nibble = 0; nibble <2; nibble++) + { + c = *nibble_ptr & ~(B30|B31); + switch (c) + { + default: + abort(); + case KBIT: + switch (operand[0].exp.X_add_number) + { + case 1: + nib = 0; + break; + case 2: + nib = 8; + break; + default: + as_bad("Need #1 or #2 here"); + break; + } + /* stop it making a fix */ + operand[0].mode = 0; + break; + case 0: + case 1: + case 2: case 3: case 4: case 5: case 6: + case 7: case 8: case 9: case 10: case 11: + case 12: case 13: case 14: case 15: + nib = c; + break; + case DISPREG: + nib = operand[0].dispreg; + break; + case IMM8: + operand[0].mode = IMM8; + nib = 0; + break; + + case DISPDST: + nib = 0; + break; + case IMM3: + if (operand[0].exp.X_add_symbol == 0) { + operand[0].mode = 0; /* stop it making a fix */ + nib = (operand[0].exp.X_add_number); + } + else as_bad("can't have symbol for bit number"); + if (nib < 0 || nib > 7) + { + as_bad("Bit number out of range %d", nib); + } + + break; + + case ABS16DST: + nib = 0; + break; + case ABS8DST: + operand[1].mode = ABS8DST; + nib = 0; + break; + case ABS8SRC: + operand[0].mode = ABS8SRC; + nib = 0; + break; + case ABS16OR8DST: + operand[1].mode = c; + + nib = 0; + + break; + + case ABS16ORREL8SRC: + operand[0].mode = c; + nib=0; + break; + + case ABS16OR8SRC: + operand[0].mode = ABS16OR8SRC; + nib = 0; + break; + case DISPSRC: + operand[0].mode = ABS16SRC; + nib = 0; + break; + + case DISP8: + operand[0].mode = DISP8; + nib = 0; + break; + + case ABS16SRC: + case IMM16: + case IGNORE: + case MEMIND: + + nib=0; + break; + case RS8: + case RS16: + case RSIND: + case RSINC: + nib = operand[0].reg; + break; + + case RD8: + case RD16: + case RDDEC: + case RDIND: + nib = operand[1].reg; + break; + + case E: + abort(); + break; + } + if (*nibble_ptr & B31) { + nib |=0x8; + } + + if (nibble == 0) { + *output_ptr = nib << 4; + } + else { + *output_ptr |= nib; + output_ptr++; + } + nibble_ptr++; + } + + } + + /* output any fixes */ + for (i = 0; i < 2; i++) + { + switch (operand[i].mode) { + case 0: + break; + + case DISP8: + check_operand(operand+i, 0x7f,"@"); + + fix_new(frag_now, + output - frag_now->fr_literal + 1, + 1, + operand[i].exp.X_add_symbol, + operand[i].exp.X_subtract_symbol, + operand[i].exp.X_add_number -1, + 1, + R_PCRBYTE); + break; + case IMM8: + check_operand(operand+i, 0xff,"#"); + /* If there is nothing else going on we can safely + reloc in place */ + if (operand[i].exp.X_add_symbol == 0) + { + output[1] = operand[i].exp.X_add_number; + } + else + { + fix_new(frag_now, + output - frag_now->fr_literal + 1, + 1, + operand[i].exp.X_add_symbol, + operand[i].exp.X_subtract_symbol, + operand[i].exp.X_add_number, + 0, + R_RELBYTE); + } + + break; + case MEMIND: + check_operand(operand+i, 0xff,"@@"); + fix_new(frag_now, + output - frag_now->fr_literal + 1, + 1, + operand[i].exp.X_add_symbol, + operand[i].exp.X_subtract_symbol, + operand[i].exp.X_add_number, + 0, + R_RELBYTE); + break; + case ABS8DST: + case ABS8SRC: + check_operand(operand+i, 0xff,"@"); + fix_new(frag_now, + output - frag_now->fr_literal + 1, + 1, + operand[i].exp.X_add_symbol, + operand[i].exp.X_subtract_symbol, + operand[i].exp.X_add_number, + 0, + R_RELBYTE); + break; + + case ABS16OR8SRC: + case ABS16OR8DST: + check_operand(operand+i, 0xffff,"@"); + + fix_new(frag_now, + output - frag_now->fr_literal + 2, + 2, + operand[i].exp.X_add_symbol, + operand[i].exp.X_subtract_symbol, + operand[i].exp.X_add_number, + 0, + R_MOVB1); + break; + + case ABS16ORREL8SRC: + check_operand(operand+i, 0xffff,"@"); + + fix_new(frag_now, + output - frag_now->fr_literal + 2, + 2, + operand[i].exp.X_add_symbol, + operand[i].exp.X_subtract_symbol, + operand[i].exp.X_add_number, + 0, + R_JMP1); + break; + + + case ABS16SRC: + case ABS16DST: + case IMM16: + case DISPSRC: + case DISPDST: + check_operand(operand+i, 0xffff,"@"); + if (operand[i].exp.X_add_symbol == 0) + { + /* This should be done with bfd */ + output[3] = operand[i].exp.X_add_number & 0xff; + output[2] = operand[i].exp.X_add_number >> 8; + + } + else + { + + fix_new(frag_now, + output - frag_now->fr_literal + 2, + 2, + operand[i].exp.X_add_symbol, + operand[i].exp.X_subtract_symbol, + operand[i].exp.X_add_number, + 0, + R_RELWORD); + } + + break; + case RS8: + case RD8: + case RS16: + case RD16: + case RDDEC: + case KBIT: + case RSINC: + case RDIND: + case RSIND: + case CCR: + + break; + default: + abort(); + } + } + +} /* This is the guts of the machine-dependent assembler. STR points to a machine dependent instruction. This funciton is supposed to emit the frags/bytes it assembles to. @@ -315,291 +902,74 @@ DEFUN(md_assemble,(str), char *op_start; char *op_end; unsigned int i; - + struct h8_op operand[2]; struct h8_opcode * opcode; + char *dot = 0; + char c; /* Drop leading whitespace */ while (*str == ' ') str++; - /* find the op code end */ for (op_start = op_end = str; *op_end != 0 && *op_end != ' '; - op_end ++) - ; + op_end ++) + { + if (*op_end == '.') { + dot = op_end+1; + *op_end = 0; + op_end+=2; + break; + } + } + + ; - if (op_end == op_start) { - as_bad("can't find opcode "); - } + if (op_end == op_start) + { + as_bad("can't find opcode "); + } + c = *op_end; + *op_end = 0; + opcode = (struct h8_opcode *) hash_find(opcode_hash_control, op_start); - if (opcode == NULL) { - as_bad("unknown opcode"); - return; - } - - -{ - int ok = 1; - int j,i; - int dispreg = 0; - struct h8_op operand[2]; - char *ptr = op_end+1; - if (opcode->noperands) - get_operand(& ptr, &operand[0],0); - else operand[0].mode = 0; - if (opcode->noperands==2) { - if (*ptr == ',') ptr++; - get_operand(& ptr, &operand[1], 1); - } - else operand[1].mode = 0; - - + if (opcode == NULL) + { + as_bad("unknown opcode"); + return; + } -{ - struct h8_opcode *this_try ; - int found = 0; - for (j = 0; j < opcode->nopcodes && !found; j++) { - this_try = opcode + j; - for (i = 0; i < opcode->noperands; i++) { - op_type op = (this_try->args.nib[i]) & ~(B30|B31); - switch (op) { - case Hex0: - case Hex1: - case Hex2: - case Hex3: - case Hex4: - case Hex5: - case Hex6: - case Hex7: - case Hex8: - case Hex9: - case HexA: - case HexB: - case HexC: - case HexD: - case HexE: - case HexF: - break; - case DISPSRC: - case DISPDST: - dispreg = operand[i].reg; - case RD8: - case RS8: - case RDIND: - case RSIND: - case RD16: - case RS16: - case CCR: - case RSINC: - case RDDEC: - if (operand[i].mode != op) goto fail; - break; - case IMM8: - /* We have an expression, called IMM16, but we know we - want an 8 bit value here */ - if (operand[i].mode != IMM16) goto fail; - operand[i].mode = IMM8; - break; - case KBIT: - case IMM16: - case IMM3: - if (operand[i].mode != IMM16) goto fail; - break; - case ABS16SRC: - case ABS8SRC: - if (operand[i].mode != ABS16SRC) goto fail; - break; - case ABS16DST: - case ABS8DST: - if (operand[i].mode != ABS16DST) goto fail; - - break; - } - } - found =1; - fail: ; + + input_line_pointer = get_operands(opcode->noperands, op_end, + operand); + *op_end = c; + opcode = get_specific(opcode, operand); + + if (opcode == 0) + { + /* Allocate 2 bytes for the insn anyway */ + char *where =frag_more(2); + where[0] = 0xde; + where[1] = 0xad; + + + as_bad("illegal operands for opcode"); + return; + } + if (opcode->size && dot) + { + if (opcode->size != *dot) + { + as_warn("mismatch between opcode size and operand size"); } - if (found == 0) - as_bad("illegal operands for opcode"); - - - /* Now we know what sort of opcodes etc, lets build the bytes - - actually we know how big the instruction will be too. So we - can get - */ -{ - char *output = frag_more(this_try->length); - char *output_ptr = output; - op_type *nibble_ptr = this_try->data.nib; - char part; - op_type c; - char high; - int nib; - top: ; - while (*nibble_ptr != E) { - int nibble; - for (nibble = 0; nibble <2; nibble++) { - c = *nibble_ptr & ~(B30|B31); - switch (c) { - default: - abort(); - case KBIT: - switch (operand[0].exp.X_add_number) { - case 1: - nib = 0; - break; - case 2: - nib = 8; - break; - default: - as_bad("Need #1 or #2 here"); - break; - } - /* stop it making a fix */ - operand[0].mode = 0; - break; - case 0: - case 1: - case 2: case 3: case 4: case 5: case 6: - case 7: case 8: case 9: case 10: case 11: - case 12: case 13: case 14: case 15: - nib = c; - break; - case DISPREG: - nib = dispreg; - break; - case IMM8: - nib = 0; - break; - - case DISPDST: - nib = 0; - break; - case IMM3: - if (operand[0].exp.X_add_symbol == 0) { - operand[0].mode = 0; /* stop it making a fix */ - nib = (operand[0].exp.X_add_number); - } - else as_bad("can't have symbol for bit number"); - break; - - case ABS16DST: - nib = 0; - break; - case DISPSRC: - case ABS16SRC: - case IMM16: - nib=0; - break; - - - case ABS8DST: - case ABS8SRC: - case IGNORE: - - - nib = 0; - break; - case DISP8: - nib = 0; - break; - - - case RS8: - case RS16: - case RSIND: - case RSINC: - - nib= operand[0].reg; - break; - case RD8: - case RD16: - case RDDEC: - case RDIND: - nib = operand[1].reg; - - break; - case E: - abort(); - break; - } - if (*nibble_ptr & B31) nib|=0x8; - if (nibble == 0) { - *output_ptr = nib << 4; - } - else { - *output_ptr |= nib; - output_ptr++; - } - nibble_ptr++; - } - - } - - /* output any fixes */ - for (i = 0; i < 2; i++) - { - switch (operand[i].mode) { - case 0: - break; - case DISP8: - fix_new(frag_now, - output - frag_now->fr_literal + 1, - 1, - operand[i].exp.X_add_symbol, - operand[i].exp.X_subtract_symbol, - operand[i].exp.X_add_number -1, - 1, - (int)r8pcrel); - break; - case IMM8: - fix_new(frag_now, - output - frag_now->fr_literal + 1, - 1, - operand[i].exp.X_add_symbol, - operand[i].exp.X_subtract_symbol, - operand[i].exp.X_add_number, - 0, - 0); - break; - - case ABS16SRC: - case ABS16DST: - case IMM16: - case DISPSRC: - case DISPDST: - fix_new(frag_now, - output - frag_now->fr_literal + 2, - 2, - operand[i].exp.X_add_symbol, - operand[i].exp.X_subtract_symbol, - operand[i].exp.X_add_number, - 0, - (int)r16); - break; - case RS8: - case RD8: - case RS16: - case RD16: - case RDDEC: - case KBIT: - case RSINC: - case RDIND: - case RSIND: - break; - default: - abort(); - } - } + } + build_bytes(opcode, operand); } -} -} -} void DEFUN(tc_crawl_symbol_chain, (headers), @@ -692,7 +1062,9 @@ md_parse_option(argP, cntP, vecP) int *cntP; char ***vecP; - {abort(); + { + return 0; + } int md_short_jump_size; @@ -770,7 +1142,8 @@ int md_estimate_size_before_relax(fragP, segment_type) register fragS *fragP; register segT segment_type; -{ printf("call tomd_estimate_size_before_relax \n"); abort(); } +{ +printf("call tomd_estimate_size_before_relax \n"); abort(); } /* Put number into target byte order */ void DEFUN(md_number_to_chars,(ptr, use, nbytes), @@ -792,3 +1165,49 @@ long md_pcrel_from(fixP) fixS *fixP; { abort(); } void tc_coff_symbol_emit_hook() { } + + +void tc_reloc_mangle(fix_ptr, intr, base) +fixS *fix_ptr; +struct internal_reloc *intr; +bfd_vma base; + +{ + symbolS *symbol_ptr; + + symbol_ptr = fix_ptr->fx_addsy; + + /* If this relocation is attached to a symbol then it's ok + to output it */ + if (fix_ptr->fx_r_type == RELOC_32) { + /* cons likes to create reloc32's whatever the size of the reloc.. + */ + switch (fix_ptr->fx_size) + { + + case 2: + intr->r_type = R_RELWORD; + break; + case 1: + intr->r_type = R_RELBYTE; + break; + default: + abort(); + + } + + } + else { + intr->r_type = fix_ptr->fx_r_type; + } + + intr->r_vaddr = fix_ptr->fx_frag->fr_address + fix_ptr->fx_where +base; + intr->r_offset = fix_ptr->fx_offset; + + if (symbol_ptr) + intr->r_symndx = symbol_ptr->sy_number; + else + intr->r_symndx = -1; + + +} diff --git a/gas/listing.c b/gas/listing.c new file mode 100644 index 0000000..c7331ac --- /dev/null +++ b/gas/listing.c @@ -0,0 +1,821 @@ +/* listing.c - mainting assembly listings + Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This file is part of GAS, the GNU Assembler. + +GAS is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GAS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GAS; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* + Contributed by Steve Chamberlain + sac@cygnus.com + + + A listing page looks like: + + LISTING_HEADER sourcefilename pagenumber + TITLE LINE + SUBTITLE LINE + linenumber address data source + linenumber address data source + linenumber address data source + linenumber address data source + + If not overridden, the listing commands are: + + .title "stuff" + Put "stuff" onto the title line + .sbttl "stuff" + Put stuff onto the subtitle line + + If these commands come within 10 lines of the top of the page, they + will affect the page they are on, as well as any subsequent page + + .eject + Thow a page + .list + Increment the enable listing counter + .nolist + Decrement the enable listing counter + + .psize Y[,X] + Set the paper size to X wide and Y high. Setting a psize Y of + zero will suppress form feeds except where demanded by .eject + + If the counter goes below zero, listing is suppressed. + + + Listings are a maintained by read calling various listing_ + functions. What happens most is that the macro NO_LISTING is not + defined (from the Makefile), then the macro LISTING_NEWLINE expands + into a call to listing_newline. The call is done from read.c, every + time it sees a newline, and -l is on the command line. + + The function listing_newline remembers the frag associated with the + newline, and creates a new frag - note that this is wasteful, but not + a big deal, since listing slows things down a lot anyway. The + function also rememebers when the filename changes. + + When all the input has finished, and gas has had a chance to settle + down, the listing is output. This is done by running down the list of + frag/source file records, and opening the files as needed and printing + out the bytes and chars associated with them. + + The only things which the architecture can change about the listing + are defined in these macros: + + LISTING_HEADER The name of the architecture + LISTING_WORD_SIZE The make of the number of bytes in a word, this determines + the clumping of the output data. eg a value of + 2 makes words look like 1234 5678, whilst 1 + would make the same value look like 12 34 56 + 78 + LISTING_LHS_WIDTH Number of words of above size for the lhs + + LISTING_LHS_WIDTH_SECOND Number of words for the data on the lhs + for the second line + + LISTING_LHS_CONT_LINES Max number of lines to use up for a continutation + LISTING_RHS_WIDTH Number of chars from the input file to print + on a line +*/ + +#include "as.h" +#include +#include "input-file.h" +#include "targ-cpu.h" + +#ifndef NO_LISTING +#ifndef LISTING_HEADER +#define LISTING_HEADER "GAS LISTING" +#endif +#ifndef LISTING_WORD_SIZE +#define LISTING_WORD_SIZE 4 +#endif +#ifndef LISTING_LHS_WIDTH +#define LISTING_LHS_WIDTH 1 +#endif +#ifndef LISTING_LHS_WIDTH_SECOND +#define LISTING_LHS_WIDTH_SECOND 1 +#endif +#ifndef LISTING_RHS_WIDTH +#define LISTING_RHS_WIDTH 100 +#endif +#ifndef LISTING_LHS_CONT_LINES +#define LISTING_LHS_CONT_LINES 4 +#endif + + + + +/* This structure remembers which files were used */ +typedef struct file_info_struct +{ + char *filename; + int linenum; + FILE *file; + struct file_info_struct *next; +} file_info_type ; + + +/* this structure rememebrs which line from which file goes into which + frag */ +typedef struct list_info_struct +{ + /* Frag which this line of source is nearest to */ + fragS *frag; + /* The actual line in the source file */ + unsigned int line; + /* Pointer to the file info struct for the file which this line + belongs to */ + file_info_type *file; + + /* Next in list */ + struct list_info_struct *next; + + + /* Pointer to any error message associated with this line */ + char *message; + + enum + { + EDICT_NONE, + EDICT_SBTTL, + EDICT_TITLE, + EDICT_NOLIST, + EDICT_LIST, + EDICT_EJECT + } edict; + char *edict_arg; + +} list_info_type; + + +static struct list_info_struct *head; +struct list_info_struct *listing_tail; +extern int listing; +extern unsigned int physical_input_line; +extern fragS *frag_now; + + +static int paper_width = 200; +static int paper_height = 60; + + +/* this static array is used to keep the text of data to be printed + before the start of the line. + It is stored so we can give a bit more info on the next line. To much, and large + initialized arrays will use up lots of paper. + */ + +static char data_buffer[100]; +static unsigned int data_buffer_size; + + +static void +DEFUN(listing_message,(name, message), + char *name AND + char *message) +{ + unsigned int l = strlen(name) + strlen(message)+1; + char *n = malloc(l); + strcpy(n,name); + strcat(n,message); + if(listing_tail != (list_info_type *)NULL) + { + listing_tail->message = n; + } + +} + + + + +void +DEFUN(listing_warning,(message), + char *message) +{ + listing_message("Warning:", message); +} + +void +DEFUN(listing_error,(message), + char *message) +{ + listing_message("Error:", message); +} + + + + extern char *file_name; +static file_info_type *file_info_head; + +static file_info_type * +DEFUN_VOID(file_info) +{ + /* Find an entry with this file name */ + file_info_type *p = file_info_head; + + while (p != (file_info_type *)NULL) + { + if (strcmp(p->filename, file_name) == 0) + return p; + p = p->next; + } + + /* Make new entry */ + + p = (file_info_type *)xmalloc(sizeof(file_info_type)); + p->next = file_info_head; + file_info_head = p; + p->filename = xmalloc(strlen(file_name)+1); + strcpy(p->filename, file_name); + p->linenum = 0; + p->file = fopen(p->filename,"r"); + return p; + +} + + +void +DEFUN(listing_newline,(ps), + char *ps) +{ + char *s = ps; + + static unsigned int last_line =0xffff ; + + + list_info_type *new; + if (physical_input_line != last_line) + { + last_line = physical_input_line; + frag_wane(frag_now); + frag_new(0); + new = (list_info_type *)malloc(sizeof(list_info_type)); + new->frag = frag_now; + new->line = physical_input_line ; + new->file = file_info(); + + if (listing_tail) + { + listing_tail->next = new; + } + else + { + head = new; + } + listing_tail = new; + new->next = (list_info_type *)NULL; + new->message = (char *)NULL; + new->edict = EDICT_NONE; + frag_wane(frag_now); + frag_new(0); + } +} + + + + +static char * +DEFUN(buffer_line,(ptr,line, size), + list_info_type *ptr AND + char *line AND + unsigned int size) +{ + unsigned int count = 0; + char *p = line; + int c = fgetc(ptr->file->file); + size -= 1; /* leave room for null */ + while (c != EOF && c != '\n') + { + if (count < size) + *p++ = c; + count++; + + c= fgetc(ptr->file->file); + } + if (c == EOF) + { + rewind(ptr->file->file); + } + + *p++ = 0; + return line; +} + + +static char *fn; + +static unsigned int eject; /* Eject pending */ +static unsigned int page; /* Current page number */ +static char *title; /* current title */ +static char *subtitle; /* current subtitle */ +static unsigned int on_page; /* number of lines printed on current page */ + + +static void +DEFUN(listing_page,(list), + list_info_type *list) +{ + /* Grope around, see if we can see a title or subtitle edict coming up + soon (we look down 10 lines of the page and see if it's there)*/ + if ((eject || (on_page >= paper_height)) && paper_height != 0) + { + unsigned int c = 10; + int had_title = 0; + int had_subtitle = 0; + + page++; + + while (c != 0 && list) + { + if (list->edict == EDICT_SBTTL && !had_subtitle) + { + had_subtitle = 1; + subtitle = list->edict_arg; + } + if (list->edict == EDICT_TITLE && !had_title) + { + had_title = 1; + title = list->edict_arg; + } + list = list->next; + c--; + } + + + if (page > 1) + { + printf("\f"); + } + + printf("%s %s \t\t\tpage %d\n", LISTING_HEADER, fn, page); + printf("%s\n", title); + printf("%s\n", subtitle); + on_page = 3; + eject = 0; + } +} + + +static unsigned int +DEFUN(calc_hex,(list), + list_info_type *list) +{ + list_info_type *first = list; + list_info_type *last = first; + unsigned int address = ~0; + + fragS *frag; + fragS *frag_ptr; + + unsigned int byte_in_frag = 0; + + int anything = 0; + + /* Find first frag which says it belongs to this line */ + frag = list->frag; + while (frag && frag->line != list) + frag = frag->fr_next; + + frag_ptr = frag; + + data_buffer_size = 0; + + /* Dump all the frags which belong to this line */ + while (frag_ptr != (fragS *)NULL && frag_ptr->line == first) + { + /* Print as many bytes from the fixed part as is sensible */ + while(byte_in_frag < frag_ptr->fr_fix && data_buffer_size < sizeof(data_buffer)-10) + { + if (address == ~0) + { + address = frag_ptr->fr_address; + } + + sprintf(data_buffer + data_buffer_size, "%02X",(frag_ptr->fr_literal[byte_in_frag]) & 0xff); + data_buffer_size += 2; + byte_in_frag++; + } + /* Print as many bytes from the variable part as is sensible */ + while (byte_in_frag < frag_ptr->fr_var * frag_ptr->fr_offset + && data_buffer_size < sizeof(data_buffer)-10) + { + if (address == ~0) + { + address = frag_ptr->fr_address; + } + data_buffer[data_buffer_size++] = '*'; + data_buffer[data_buffer_size++] = '*'; + + byte_in_frag++; + } + frag_ptr = frag_ptr->fr_next; + } + data_buffer[data_buffer_size++] = 0; + return address; +} + + + + + + +static void +DEFUN(print_lines,(list, string, address), +list_info_type *list AND +char *string AND +unsigned int address) +{ + unsigned int idx; + unsigned int nchars; + unsigned int lines; + unsigned int byte_in_word =0; + char *src = data_buffer; + + /* Print the stuff on the first line */ + listing_page(list); + nchars = (LISTING_WORD_SIZE*2 +1) * LISTING_LHS_WIDTH ; + /* Print the hex for the first line */ + if (address == ~0) + { + printf("% 4d ", list->line); + for (idx = 0; idx < nchars; idx++) + printf(" "); + + printf("\t%s\n", string ? string : ""); + on_page++; + listing_page(0); + + } + else + { + if (had_errors()) + { + printf("% 4d ???? ", list->line); + } + else + { + printf("% 4d %04x ", list->line, address); + } + + /* And the data to go along with it */ + idx = 0; + + while (*src && idx < nchars) + { + printf("%c%c", src[0], src[1]); + src += 2; + byte_in_word++; + if (byte_in_word == LISTING_WORD_SIZE) + { + printf(" "); + idx++; + byte_in_word = 0; + } + idx+=2; + } + + for (;idx < nchars; idx++) + printf(" "); + + printf("\t%s\n", string ? string : ""); + on_page++; + listing_page(list); + if (list->message) + { + printf("**** %s\n",list->message); + listing_page(list); + on_page++; + } + + for (lines = 0; + lines < LISTING_LHS_CONT_LINES + && *src; + lines++) { + nchars = ((LISTING_WORD_SIZE*2) +1) * LISTING_LHS_WIDTH_SECOND -1; + idx = 0; + /* Print any more lines of data, but more compactly */ + printf("% 4d ", list->line); + + while (*src && idx < nchars) + { + printf("%c%c", src[0], src[1]); + src+=2; + idx+=2; + byte_in_word++; + if (byte_in_word == LISTING_WORD_SIZE) + { + printf(" "); + idx++; + byte_in_word = 0; + } + } + + printf("\n"); + on_page++; + listing_page(list); + + } + + + } +} + + + + + + +static void +DEFUN_VOID(list_symbol_table) +{ + extern symbolS *symbol_rootP; + + symbolS *ptr ; + eject = 1; + listing_page(0); + printf("DEFINED SYMBOLS\n"); + on_page++; + + for (ptr = symbol_rootP; ptr != (symbolS*)NULL; ptr = symbol_next(ptr)) + { + if (ptr->sy_frag->line) + { + printf("%20s:%-5d %2d:%08x %s \n", + ptr->sy_frag->line->file->filename, + ptr->sy_frag->line->line, + S_GET_SEGMENT(ptr), + S_GET_VALUE(ptr), + S_GET_NAME(ptr)); + on_page++; + listing_page(0); + + } + + } + printf("\n"); + on_page++; + listing_page(0); + printf("UNDEFINED SYMBOLS\n"); + on_page++; + listing_page(0); + + for (ptr = symbol_rootP; ptr != (symbolS*)NULL; ptr = symbol_next(ptr)) + { + if (ptr->sy_frag->line == 0) + { + + printf("%s\n", S_GET_NAME(ptr)); + on_page++; + listing_page(0); + + } + } +} + +void +DEFUN(listing_listing,(name), + char *name) +{ + list_info_type *list = head; + unsigned int page= 1; + unsigned int prev = 0; + char *message; + char *buffer; + char *p; + unsigned int addr = 0; + int on_page = 0; + int show_listing = 1; + + buffer = malloc(LISTING_RHS_WIDTH); + eject = 1; + list = head; + + while (list != (list_info_type *)NULL && 0) + { + if (list->next) + list->frag = list->next->frag; + list = list->next; + + } + + list = head->next; + + + while ( list) + { + p = buffer_line(list, buffer, LISTING_RHS_WIDTH > paper_width ? + paper_width : LISTING_RHS_WIDTH); + + switch (list->edict) { + case EDICT_LIST: + show_listing++; + break; + case EDICT_NOLIST: + show_listing--; + break; + case EDICT_EJECT: + break; + case EDICT_NONE: + break; + case EDICT_TITLE: + title = list->edict_arg; + break; + case EDICT_SBTTL: + subtitle = list->edict_arg; + break; + default: + abort(); + } + + if (show_listing > 0) + { + /* Scan down the list and print all the stuff which can be done + with this line (or lines) */ + message = 0; + + + print_lines(list, p, calc_hex(list)); + + if (list->edict == EDICT_EJECT) + { + eject = 1; + } + } + list = list->next; + } + free(buffer); +} + +void +DEFUN(listing_print,(name), + char *name) +{ + title = ""; + subtitle = ""; + + if (listing & LISTING_NOFORM) + { + paper_height = 0; + } + + if (listing & LISTING_LISTING) + { + listing_listing(name); + + } + if (listing & LISTING_SYMBOLS) + { + list_symbol_table(); + } +} + + +void +DEFUN(listing_file,(name), +char *name) +{ + fn = name; +} + +void +DEFUN_VOID(listing_eject) +{ + listing_tail->edict = EDICT_EJECT; +} + +void +DEFUN_VOID(listing_flags) +{ + +} +void +DEFUN(listing_list,(on), + unsigned int on) +{ + listing_tail->edict = on ? EDICT_LIST : EDICT_NOLIST; +} + + +void +DEFUN_VOID(listing_psize) +{ + paper_height = get_absolute_expression(); + + if (paper_height < 0 || paper_height > 1000) + { + paper_height = 0; + as_warn("strantge paper height, set to no form"); + } + if (*input_line_pointer == ',') + { + input_line_pointer++; + paper_width = get_absolute_expression(); + } +} + + +void +DEFUN(listing_title,(depth), + unsigned int depth) +{ + char *start; + char *title; + unsigned int length; + + SKIP_WHITESPACE(); + if (*input_line_pointer=='\"') { + input_line_pointer++; + start = input_line_pointer; + + while (*input_line_pointer) + { + if (*input_line_pointer == '\"') + { + length = input_line_pointer - start; + title = malloc(length + 1); + memcpy(title, start, length); + title[length] = 0; + listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE; + listing_tail->edict_arg = title; + input_line_pointer++; + demand_empty_rest_of_line(); + return; + } + else if (*input_line_pointer == '\n') + { + as_bad("New line in title"); + demand_empty_rest_of_line(); + return; + } + else + { + input_line_pointer++; + } + } + } + else + { + as_bad("expecting title in quotes"); + } +} + + +#else + + +/* Dummy functions for when compiled without listing enabled */ + +void +DEFUN_VOID(listing_flags) +{ + s_ignore(); +} + +void DEFUN_VOID(listing_list) +{ + s_ignore(); +} + +void DEFUN_VOID(listing_eject) +{ + s_ignore(); +} +void DEFUN(listing_psize) +{ + s_ignore(); +} + +void DEFUN(listing_title, (depth), +unsigned int depth) +{ + s_ignore(); +} +void +DEFUN(listing_file,(name), +char *name) +{ + +} + +void DEFUN(listing_newline,(name), +char *name) +{ + +} + + +#endif diff --git a/gas/listing.h b/gas/listing.h new file mode 100644 index 0000000..4339457 --- /dev/null +++ b/gas/listing.h @@ -0,0 +1,20 @@ + +#ifndef NO_LISTING +#define LISTING_NEWLINE() if (listing) listing_newline(input_line_pointer); +#else +#define LISTING_NEWLINE() +#endif +void EXFUN(listing_title,(unsigned int depth)); +void EXFUN(listing_list,()); +void EXFUN(listing_flags,()); +void EXFUN(listing_psize,()); +void EXFUN(listing_eject,()); +void EXFUN(listing_width,(unsigned int x)); + + +#define LISTING_LISTING 1 +#define LISTING_SYMBOLS 2 +#define LISTING_NOFORM 4 +#define LISTING_DEFAULT 3 + + -- cgit v1.1