Esempio n. 1
0
int main(int argc, char **argv)
{
	void (*parse_init)(char *file);
	asm86_t *(*get_instruction)(void);
	void (*emit_init)(char *file, const char *banner);
	void (*emit_instruction)(asm86_t *instr);
	char *lang_parse, *lang_emit, *input_file, *output_file;
	asm86_t *instr;
	char banner[80];

	if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'm') {
		if (strcmp(argv[1], "-mi86") == 0) {
			set_use16();
		} else
		if (strcmp(argv[1], "-mi386") == 0) {
			set_use32();
		} else {
			fprintf(stderr, "asmconv: '%s': unknown machine\n",
				argv[1]+2);
		}
		argc--;
		argv++;
	}

	if (argc > 3) {
		fprintf(stderr, "Usage: gas2ack [input-file [output-file]]\n");
		exit(EXIT_FAILURE);
	}

	input_file= argc < 1 ? nil : argv[1];
	output_file= argc < 2 ? nil : argv[2];

	parse_init= gnu_parse_init;
	get_instruction= gnu_get_instruction;

	emit_init= ack_emit_init;
	emit_instruction= ack_emit_instruction;

	sprintf(banner, "Translated from GNU to ACK by gas2ack");

	/* get localy defined labels first */
	(*parse_init)(input_file);
	for (;;) {
		instr= (*get_instruction)();
		if (instr == nil) break;
		del_asm86(instr);
	}

	(*parse_init)(input_file);
	(*emit_init)(output_file, banner);
	for (;;) {
		instr= (*get_instruction)();
		(*emit_instruction)(instr);
		if (instr == nil) break;
		del_asm86(instr);
	}
	exit(err_code);
}
Esempio n. 2
0
int main(int argc, char **argv)
{
	void (*parse_init)(char *file);
	asm86_t *(*get_instruction)(void);
	void (*emit_init)(char *file, const char *banner);
	void (*emit_instruction)(asm86_t *instr);
	char *lang_parse, *lang_emit, *input_file, *output_file;
	asm86_t *instr;
	char banner[80];

	if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'm') {
		if (strcmp(argv[1], "-mi86") == 0) {
			set_use16();
		} else
		if (strcmp(argv[1], "-mi386") == 0) {
			set_use32();
		} else {
			fprintf(stderr, "asmconv: '%s': unknown machine\n",
				argv[1]+2);
		}
		argc--;
		argv++;
	}

	if (argc < 3 || argc > 5) {
		fprintf(stderr,
"Usage: asmconv <input-type> <output-type> [input-file [output-file]]\n");
		exit(EXIT_FAILURE);
	}

	lang_parse= argv[1];
	lang_emit= argv[2];
	input_file= argc < 4 ? nil : argv[3];
	output_file= argc < 5 ? nil : argv[4];

	/* Choose the parsing routines. */
	if (strcmp(lang_parse, "ack") == 0) {
		/* Standard ACK. */
		parse_init= ack_parse_init;
		get_instruction= ack_get_instruction;
	} else
	if (strcmp(lang_parse, "ncc") == 0) {
		/* ACK Xenix assembly, a black sheep among ACK assemblies. */
		parse_init= ncc_parse_init;
		get_instruction= ncc_get_instruction;
	} else
	if (strcmp(lang_parse, "gnu") == 0) {
		/* GNU assembly.  Parser by R.S. Veldema. */
		parse_init= gnu_parse_init;
		get_instruction= gnu_get_instruction;
	} else
	if (strcmp(lang_parse, "bas") == 0) {
		/* Bruce Evans' assembler. */
		parse_init= bas_parse_init;
		get_instruction= bas_get_instruction;
	} else {
		fprintf(stderr, "asmconv: '%s': unknown input language\n",
			lang_parse);
		exit(EXIT_FAILURE);
	}

	/* Choose the output language. */
	if (strcmp(lang_emit, "ack") == 0) {
		/* Standard ACK. */
		emit_init= ack_emit_init;
		emit_instruction= ack_emit_instruction;
	} else
	if (strcmp(lang_emit, "ncc") == 0) {
		/* ACK Xenix assembly, can be read by BAS and the 8086 ACK
		 * ANSI C compiler.  (Allows us to compile the Boot Monitor.)
		 */
		emit_init= ncc_emit_init;
		emit_instruction= ncc_emit_instruction;
	} else
	if (strcmp(lang_emit, "gnu") == 0) {
		/* GNU assembler.  So we can assemble the ACK stuff among the
		 * kernel sources and in the library.
		 */
		emit_init= gnu_emit_init;
		emit_instruction= gnu_emit_instruction;
	} else {
		fprintf(stderr, "asmconv: '%s': unknown output language\n",
			lang_emit);
		exit(EXIT_FAILURE);
	}

	sprintf(banner, "Translated from %s to %s by asmconv %s",
					lang_parse, lang_emit, version);

	/* get localy defined labels first */
	(*parse_init)(input_file);
	for (;;) {
		instr= (*get_instruction)();
		if (instr == nil) break;
		del_asm86(instr);
	}

	(*parse_init)(input_file);
	(*emit_init)(output_file, banner);
	for (;;) {
		instr= (*get_instruction)();
		(*emit_instruction)(instr);
		if (instr == nil) break;
		del_asm86(instr);
	}
	exit(err_code);
}
Esempio n. 3
0
int main(int argc, char **argv)
{
	void (*parse_init)(char *file);
	asm86_t *(*get_instruction)(void);
	void (*emit_init)(char *file, const char *banner);
	void (*emit_instruction)(asm86_t *instr);
	char *lang_parse, *lang_emit, *input_file, *output_file;
	asm86_t *instr;
	char banner[80];
	char c;
	opterr = 0;

   while ((c = getopt (argc, argv, "m:u")) != -1)
      switch (c)
      {
      case 'm':
         if (strcmp(optarg, "i86") == 0) {
            set_use16();
         } else
         if (strcmp(optarg, "i386") == 0) {
            set_use32();
         }
         else {
            fprintf(stderr, "asmconv: '%s': unknown machine\n",
                    optarg);
            exit(EXIT_FAILURE);
         }
         break;
      case 'u':
         enable_underscore_mode();
         break;
      default:
         fprintf(stderr, "Usage: gas2ack [input-file [output-file]]\n");
         exit(EXIT_FAILURE);
      }

	if ((argc - optind < 1) || (argc - optind  > 2)) {
		fprintf(stderr, "Usage: gas2ack [input-file [output-file]]\n");
		exit(EXIT_FAILURE);
	}

	input_file= (argc - optind) < 1 ? nil : argv[optind];
	output_file= (argc - optind) < 2 ? nil : argv[optind+1];

	parse_init= gnu_parse_init;
	get_instruction= gnu_get_instruction;

	emit_init= ack_emit_init;
	emit_instruction= ack_emit_instruction;

	sprintf(banner, "Translated from GNU to ACK by gas2ack");

	/* get localy defined labels first */
	(*parse_init)(input_file);
	for (;;) {
		instr= (*get_instruction)();
		if (instr == nil) break;
		del_asm86(instr);
	}

	(*parse_init)(input_file);
	(*emit_init)(output_file, banner);
	for (;;) {
		instr= (*get_instruction)();
		(*emit_instruction)(instr);
		if (instr == nil) break;
		del_asm86(instr);
	}
	exit(err_code);
}
Esempio n. 4
0
static asm86_t *ack_get_statement(void)
/* Get a pseudo op or machine instruction with arguments. */
{
	token_t *t= get_token(0);
	asm86_t *a;
	mnemonic_t *m;
	int n;
	int prefix_seen;
	int oaz_prefix;
	int deref;

	assert(t->type == T_WORD);

	if (strcmp(t->name, ".sect") == 0) {
		/* .sect .text etc.  Accept only four segment names. */
		skip_token(1);
		t= get_token(0);
		if (t->type != T_WORD || (
			strcmp(t->name, ".text") != 0
			&& strcmp(t->name, ".rom") != 0
			&& strcmp(t->name, ".data") != 0
			&& strcmp(t->name, ".bss") != 0
			&& strcmp(t->name, ".end") != 0
		)) {
			parse_err(1, t, "weird section name to .sect\n");
			return nil;
		}
	}
	a= new_asm86();

	/* Process instruction prefixes. */
	oaz_prefix= 0;
	for (prefix_seen= 0;; prefix_seen= 1) {
		if (strcmp(t->name, "o16") == 0) {
			if (use16()) {
				parse_err(1, t, "o16 in an 8086 section\n");
			}
			oaz_prefix|= OPZ;
		} else
		if (strcmp(t->name, "o32") == 0) {
			if (use32()) {
				parse_err(1, t, "o32 in an 80386 section\n");
			}
			oaz_prefix|= OPZ;
		} else
		if (strcmp(t->name, "a16") == 0) {
			if (use16()) {
				parse_err(1, t, "a16 in an 8086 section\n");
			}
			oaz_prefix|= ADZ;
		} else
		if (strcmp(t->name, "a32") == 0) {
			if (use32()) {
				parse_err(1, t, "a32 in an 80386 section\n");
			}
			oaz_prefix|= ADZ;
		} else
		if (strcmp(t->name, "rep") == 0
			|| strcmp(t->name, "repe") == 0
			|| strcmp(t->name, "repne") == 0
			|| strcmp(t->name, "repz") == 0
			|| strcmp(t->name, "repnz") == 0
		) {
			if (a->rep != ONCE) {
				parse_err(1, t,
					"can't have more than one rep\n");
			}
			switch (t->name[3]) {
			case 0:		a->rep= REP;	break;
			case 'e':
			case 'z':	a->rep= REPE;	break;
			case 'n':	a->rep= REPNE;	break;
			}
		} else
		if (strchr("cdefgs", t->name[0]) != nil
					&& strcmp(t->name+1, "seg") == 0) {
			if (a->seg != DEFSEG) {
				parse_err(1, t,
				"can't have more than one segment prefix\n");
			}
			switch (t->name[0]) {
			case 'c':	a->seg= CSEG;	break;
			case 'd':	a->seg= DSEG;	break;
			case 'e':	a->seg= ESEG;	break;
			case 'f':	a->seg= FSEG;	break;
			case 'g':	a->seg= GSEG;	break;
			case 's':	a->seg= SSEG;	break;
			}
		} else
		if (!prefix_seen) {
			/* No prefix here, get out! */
			break;
		} else {
			/* No more prefixes, next must be an instruction. */
			if (t->type != T_WORD
				|| (m= search_mnem(t->name)) == nil
				|| m->optype == PSEUDO
			) {
				parse_err(1, t,
		"machine instruction expected after instruction prefix\n");
				del_asm86(a);
				return nil;
			}
			if (oaz_prefix != 0 && m->optype != JUMP
						&& m->optype != WORD) {
				parse_err(1, t,
			"'%s' can't have an operand size prefix\n", m->name);
			}
			break;
		}

		/* Skip the prefix and extra newlines. */
		do {
			skip_token(1);
		} while ((t= get_token(0))->symbol == ';');
	}

	/* All the readahead being done upsets the line counter. */
	a->line= t->line;

	/* Read a machine instruction or pseudo op. */
	if ((m= search_mnem(t->name)) == nil) {
		parse_err(1, t, "unknown instruction '%s'\n", t->name);
		del_asm86(a);
		return nil;
	}
	a->opcode= m->opcode;
	a->optype= m->optype;
	a->oaz= oaz_prefix;

	switch (a->opcode) {
	case IN:
	case OUT:
	case INT:
		deref= 0;
		break;
	default:
		deref= (a->optype >= BYTE);
	}
	n= 1;
	if (get_token(1)->symbol != ';'
			&& (a->args= ack_get_oplist(&n, deref)) == nil) {
		del_asm86(a);
		return nil;
	}
	if (get_token(n)->symbol != ';') {
		parse_err(1, t, "garbage at end of instruction\n");
		del_asm86(a);
		return nil;
	}
	switch (a->opcode) {
	case DOT_ALIGN:
		/* Restrict .align to have a single numeric argument, some
		 * assemblers think of the argument as a power of two, so
		 * we need to be able to change the value.
		 */
		if (a->args == nil || a->args->operator != 'W'
					|| !isanumber(a->args->name)) {
			parse_err(1, t,
			  ".align is restricted to one numeric argument\n");
			del_asm86(a);
			return nil;
		}
		break;
	case JMPF:
	case CALLF:
		/* NCC jmpf off,seg  ->  ACK jmpf seg:off */
		if (dialect == NCC && a->args != nil
						&& a->args->operator == ',') {
			expression_t *t;

			t= a->args->left;
			a->args->left= a->args->right;
			a->args->right= t;
			break;
		}
		/*FALL THROUGH*/
	case JMP:
	case CALL:
		/* NCC jmp @(reg)  ->  ACK jmp (reg) */
		if (dialect == NCC && a->args != nil && (
			(a->args->operator == '('
				&& a->args->middle != nil
				&& a->args->middle->operator == 'O')
			|| (a->args->operator == 'O'
				&& a->args->left == nil
				&& a->args->middle != nil
				&& a->args->right == nil)
		)) {
			expression_t *t;

			t= a->args;
			a->args= a->args->middle;
			t->middle= nil;
			del_expr(t);
			if (a->args->operator == 'B') a->args->operator= 'W';
		}
		break;
	default:;
	}
	skip_token(n+1);
	return a;
}
Esempio n. 5
0
static asm86_t *gnu_get_statement(void)
/* Get a pseudo op or machine instruction with arguments. */
{
	token_t *t= get_token(0);
	token_t *tn;
	asm86_t *a;
	mnemonic_t *m;
	int n;
	int prefix_seen;
	int deref;

	assert(t->type == T_WORD);

	a= new_asm86();

	/* Process instruction prefixes. */
	for (prefix_seen= 0;; prefix_seen= 1) {
		if (strcmp(t->name, "rep") == 0
			|| strcmp(t->name, "repe") == 0
			|| strcmp(t->name, "repne") == 0
			|| strcmp(t->name, "repz") == 0
			|| strcmp(t->name, "repnz") == 0
		) {
			if (a->rep != ONCE) {
				parse_err(1, t,
					"can't have more than one rep\n");
			}
			switch (t->name[3]) {
			case 0:		a->rep= REP;	break;
			case 'e':
			case 'z':	a->rep= REPE;	break;
			case 'n':	a->rep= REPNE;	break;
			}
		} else
		if (!prefix_seen) {
			/* No prefix here, get out! */
			break;
		} else {
			/* No more prefixes, next must be an instruction. */
			if (t->type != T_WORD
				|| (m= search_mnem(t->name)) == nil
				|| m->optype == PSEUDO
			) {
				parse_err(1, t,
		"machine instruction expected after instruction prefix\n");
				del_asm86(a);
				return nil;
			}
			break;
		}

		/* Skip the prefix and extra newlines. */
		do {
			skip_token(1);
		} while ((t= get_token(0))->symbol == ';');
	}

	/* All the readahead being done upsets the line counter. */
	a->line= t->line;

	/* Read a machine instruction or pseudo op. */
	if ((m= search_mnem(t->name)) == nil) {
		/* we assume that unknown stuff is part of unresolved macro */
		a->opcode = UNKNOWN;
		if (zap_unknown(a)) {
			parse_err(1, t, "unknown instruction '%s'\n", t->name);
			del_asm86(a);
			return nil;
		}
		return a;
	}
	a->opcode= m->opcode;
	a->optype= m->optype;
	a->oaz= 0;
	if (a->optype == OWORD) {
		a->oaz|= OPZ;
		a->optype= WORD;
	}
	else if (a->optype == JUMP16) {
		a->oaz|= OPZ;
		a->optype= JUMP;
	}

	switch (a->opcode) {
	case IN:
	case OUT:
	case INT:
		deref= 0;
		break;
	default:
		deref= (a->optype >= BYTE);
	}
	n= 1;
	if (get_token(1)->type != T_COMMENT && get_token(1)->symbol != ';'
			&& (a->args= gnu_get_oplist(a, &n, deref)) == nil) {
		del_asm86(a);
		return nil;
	}
	tn = get_token(n);
	if (tn->type == T_COMMENT) {
		a->raw_string = malloc(tn->len + 1);
		if (!a->raw_string)
			return NULL;

		strcpy(a->raw_string, tn->name);
	} else
	if (get_token(n)->symbol != ';') {
		parse_err(1, t, "garbage at end of instruction\n");
		del_asm86(a);
		return nil;
	}
	if (!is_pseudo(a->opcode)) {
		/* GNU operand order is the other way around. */
		expression_t *e, *t;

		e= a->args;
		while (e != nil && e->operator == ',') {
			t= e->right; e->right= e->left; e->left= t;
			e= e->left;
		}
	}
	switch (a->opcode) {
	case DOT_ALIGN:
		/* Delete two argument .align, because ACK can't do it.
		 */
		if (a->args == nil || a->args->operator != 'W') {	
			del_asm86(a);
			return nil;
		}
		if (a->args != nil && a->args->operator == 'W'
			&& isanumber(a->args->name)
		) {	
			unsigned n;
			char num[sizeof(int) * CHAR_BIT / 3 + 1];

			n= strtoul(a->args->name, nil, 0);
			sprintf(num, "%u", n);
			deallocate(a->args->name);
			a->args->name= copystr(num);
		}
		break;
	case DOT_DEFINE:
	case DOT_EXTERN:
		syms_add_global_csl(a->args);
		break;
	case DOT_COMM:
		syms_add_global(a->args->left->name);
		break;
	case DOT_LCOMM:
		syms_add(a->args->left->name);
		break;
	case JMPF:
	case CALLF:
		/*FALL THROUGH*/
	case JMP:
	case CALL:
		break;
	default:;
	}
	skip_token(n+1);
	return a;
}