mips/masm/main.c

171 lines
3 KiB
C
Raw Normal View History

2024-09-10 22:23:46 +00:00
#include <unistd.h>
#include <merror.h>
#include <string.h>
#include <stdio.h>
2024-09-10 22:23:46 +00:00
#include "gen.h"
#include "masm.h"
#include "asm/elf32.h"
2024-09-10 22:23:46 +00:00
void help(void) {
printf(
"usage: masm [options] source.asm\n"
"\n"
"options: \n"
" -h print the help message \n"
" -g assume undefined symbols are external\n"
" -o <output> specify the object file output name \n"
" -a <abi> specify mips abi used [none, o32] \n"
" default: o32 \n"
" -i <isa> mips machine isa to assemble for [mips1, mips32r2, mips32r6] \n"
" default: mips32r6\n"
" -f <format> specify the object file format [elf32] \n"
" defualt: elf32\n"
);
}
static int read_isa(enum isa *isa, const char *str)
{
#define __ISA_CHK(name) \
if (strcasecmp(#name, str) == 0) { \
*isa = ISA_ ##name; \
return M_SUCCESS; \
} \
__ISA_CHK(MIPS1);
__ISA_CHK(MIPS32R2);
__ISA_CHK(MIPS32R6);
ERROR("invalid isa '%s'", str);
return M_ERROR;
}
static int read_abi(enum abi *abi, const char *str)
{
#define __ABI_CHK(name) \
if (strcasecmp(#name, str) == 0) { \
*abi = ABI_ ##name; \
return M_SUCCESS; \
} \
__ABI_CHK(O32);
__ABI_CHK(NONE);
ERROR("invalid abi '%s'", str);
return M_ERROR;
}
static int read_format(enum format *format, const char *str)
{
#define __FORMAT_CHK(name) \
if (strcasecmp(#name, str) == 0) { \
*format = FORMAT_ ##name; \
return M_SUCCESS; \
} \
__FORMAT_CHK(ELF32);
ERROR("invalid format '%s'", str);
return M_ERROR;
}
static int generate(struct generator *gen, struct arguments *args)
{
if (generator_init(args->in_file, gen))
return M_ERROR;
switch (args->isa) {
case ISA_MIPS1:
return generate_mips1(gen);
case ISA_MIPS32R2:
return generate_mips32r2(gen);
case ISA_MIPS32R6:
return generate_mips32r6(gen);
}
return M_ERROR;
}
static int assemble(struct arguments *args)
{
struct generator gen;
int res = M_SUCCESS;
if (generate(&gen, args))
return M_ERROR;
switch (args->format) {
case FORMAT_ELF32:
res = assemble_elf32(&gen, args);
break;
default:
res = M_ERROR;
break;
}
generator_free(&gen);
return res;
2024-09-10 22:23:46 +00:00
}
int main(int argc, char **argv) {
struct arguments args = {
2024-09-10 22:23:46 +00:00
.in_file = NULL,
.out_file = "out.o",
.extern_undefined = false,
.isa = ISA_MIPS32R6,
.abi = ABI_O32,
.format = FORMAT_ELF32
2024-09-10 22:23:46 +00:00
};
int c;
while ((c = getopt(argc, argv, "hgo:a:i:f:")) != 1) {
2024-09-10 22:23:46 +00:00
switch(c) {
case 'h':
help();
return M_SUCCESS;
case 'g':
args.extern_undefined = true;
break;
2024-09-10 22:23:46 +00:00
case 'o':
args.out_file = optarg;
break;
case 'a':
if (read_abi(&args.abi, optarg))
return M_ERROR;
break;
case 'i':
if (read_isa(&args.isa, optarg))
return M_ERROR;
break;
case 'f':
if (read_format(&args.format, optarg))
return M_ERROR;
break;
2024-09-10 22:23:46 +00:00
case '?':
return M_ERROR;
default:
goto next;
}
}
next:
if (optind < argc - 1) {
ERROR("too many source files passed");
return M_ERROR;
}
if (optind >= argc) {
ERROR("no source files passed");
return M_ERROR;
}
args.in_file = argv[optind];
return assemble(&args);
}