aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Chambers <[email protected]>2021-10-09 12:14:13 +1300
committerAndrew Chambers <[email protected]>2021-10-09 12:14:13 +1300
commit08716714c914e696ffbd1410fa7f16a0bc18ad1c (patch)
tree6dba906e095e999bb2aefe36d64ff3141f705e33
parent8c0f425c60720ad364dea03722df2bba2b863405 (diff)
More instructions, refactor.
-rw-r--r--asm.peg113
-rw-r--r--main.c166
-rw-r--r--minias.h20
-rw-r--r--test/test.sh11
4 files changed, 198 insertions, 112 deletions
diff --git a/asm.peg b/asm.peg
index 256603d..5d9db3b 100644
--- a/asm.peg
+++ b/asm.peg
@@ -35,80 +35,99 @@ instr =
"nop" { $$.kind = ASM_NOP; }
| "leave" { $$.kind = ASM_LEAVE; }
| "ret" { $$.kind = ASM_RET; }
+ | i:push { $$ = i; }
+ | i:pop { $$ = i; }
+ | i:call { $$ = i; }
| i:jmp { $$ = i; }
- | i:xchg { $$ = i; }
| i:add { $$ = i; }
| i:and { $$ = i; }
| i:lea { $$ = i; }
| i:mov { $$ = i; }
| i:or { $$ = i; }
| i:sub { $$ = i; }
+ | i:xchg { $$ = i; }
| i:xor { $$ = i; }
+push =
+ "push" (
+ 'q'? ws s:r64 { $$ = INSTR1(0, s); }
+ | 'q' ws s:m { $$ = INSTR1(1, s); }
+ ) { $$.instr2.kind = ASM_PUSH; }
+
+pop =
+ "pop" (
+ 'q'? ws d:r64 { $$ = INSTR1(0, d); }
+ | 'q' ws d:m { $$ = INSTR1(1, d); }
+ ) { $$.instr2.kind = ASM_POP; }
+
+call =
+ "call" 'q'? ws t:ident
+ { $$.call = (Call){ .kind = ASM_CALL, .target=t.ident.name } ; }
+
jmp =
"jmp" ws t:ident
{ $$.jmp = (Jmp){ .kind = ASM_JMP, .target=t.ident.name } ; }
lea =
"lea" (
- 'w'? ws s:m ws? ',' ws? d:r16 { $$ = INSTR(0, s, d); }
- | 'l'? ws s:m ws? ',' ws? d:r32 { $$ = INSTR(1, s, d); }
- | 'q'? ws s:m ws? ',' ws? d:r64 { $$ = INSTR(2, s, d); }
- ) { $$.instr.kind = ASM_LEA; }
+ 'w'? ws s:m ws? ',' ws? d:r16 { $$ = INSTR2(0, s, d); }
+ | 'l'? ws s:m ws? ',' ws? d:r32 { $$ = INSTR2(1, s, d); }
+ | 'q'? ws s:m ws? ',' ws? d:r64 { $$ = INSTR2(2, s, d); }
+ ) { $$.instr2.kind = ASM_LEA; }
imm-rm-opargs =
- 'b' ws s:imm8 ws? ',' ws? d:m { $$ = INSTR(0, s, d); }
- | 'w' ws s:imm16 ws? ',' ws? d:m { $$ = INSTR(1, s, d); }
- | 'l' ws s:imm32 ws? ',' ws? d:m { $$ = INSTR(2, s, d); }
- | 'q' ws s:imm32 ws? ',' ws? d:m { $$ = INSTR(3, s, d); }
- | 'b'? ws s:imm8 ws? ',' ws? d:r8 { $$ = INSTR(4, s, d); }
- | 'w'? ws s:imm16 ws? ',' ws? d:r16 { $$ = INSTR(5, s, d); }
- | 'l'? ws s:imm32 ws? ',' ws? d:r32 { $$ = INSTR(6, s, d); }
- | 'q'? ws s:imm32 ws? ',' ws? d:r64 { $$ = INSTR(7, s, d); }
+ 'b' ws s:imm8 ws? ',' ws? d:m { $$ = INSTR2(0, s, d); }
+ | 'w' ws s:imm16 ws? ',' ws? d:m { $$ = INSTR2(1, s, d); }
+ | 'l' ws s:imm32 ws? ',' ws? d:m { $$ = INSTR2(2, s, d); }
+ | 'q' ws s:imm32 ws? ',' ws? d:m { $$ = INSTR2(3, s, d); }
+ | 'b'? ws s:imm8 ws? ',' ws? d:r8 { $$ = INSTR2(4, s, d); }
+ | 'w'? ws s:imm16 ws? ',' ws? d:r16 { $$ = INSTR2(5, s, d); }
+ | 'l'? ws s:imm32 ws? ',' ws? d:r32 { $$ = INSTR2(6, s, d); }
+ | 'q'? ws s:imm32 ws? ',' ws? d:r64 { $$ = INSTR2(7, s, d); }
r-rm-opargs =
- 'b'? ws s:m ws? ',' ws? d:r8 { $$ = INSTR(0, s, d); }
- | 'w'? ws s:m ws? ',' ws? d:r16 { $$ = INSTR(1, s, d); }
- | 'l'? ws s:m ws? ',' ws? d:r32 { $$ = INSTR(2, s, d); }
- | 'q'? ws s:m ws? ',' ws? d:r64 { $$ = INSTR(3, s, d); }
- | 'b'? ws s:r8 ws? ',' ws? d:m { $$ = INSTR(4, s, d); }
- | 'w'? ws s:r16 ws? ',' ws? d:m { $$ = INSTR(5, s, d); }
- | 'l'? ws s:r32 ws? ',' ws? d:m { $$ = INSTR(6, s, d); }
- | 'q'? ws s:r64 ws? ',' ws? d:m { $$ = INSTR(7, s, d); }
- | 'b'? ws s:r8 ws? ',' ws? d:r8 { $$ = INSTR(8, s, d); }
- | 'w'? ws s:r16 ws? ',' ws? d:r16 { $$ = INSTR(9, s, d); }
- | 'l'? ws s:r32 ws? ',' ws? d:r32 { $$ = INSTR(10, s, d); }
- | 'q'? ws s:r64 ws? ',' ws? d:r64 { $$ = INSTR(11, s, d); }
+ 'b'? ws s:m ws? ',' ws? d:r8 { $$ = INSTR2(0, s, d); }
+ | 'w'? ws s:m ws? ',' ws? d:r16 { $$ = INSTR2(1, s, d); }
+ | 'l'? ws s:m ws? ',' ws? d:r32 { $$ = INSTR2(2, s, d); }
+ | 'q'? ws s:m ws? ',' ws? d:r64 { $$ = INSTR2(3, s, d); }
+ | 'b'? ws s:r8 ws? ',' ws? d:m { $$ = INSTR2(4, s, d); }
+ | 'w'? ws s:r16 ws? ',' ws? d:m { $$ = INSTR2(5, s, d); }
+ | 'l'? ws s:r32 ws? ',' ws? d:m { $$ = INSTR2(6, s, d); }
+ | 'q'? ws s:r64 ws? ',' ws? d:m { $$ = INSTR2(7, s, d); }
+ | 'b'? ws s:r8 ws? ',' ws? d:r8 { $$ = INSTR2(8, s, d); }
+ | 'w'? ws s:r16 ws? ',' ws? d:r16 { $$ = INSTR2(9, s, d); }
+ | 'l'? ws s:r32 ws? ',' ws? d:r32 { $$ = INSTR2(10, s, d); }
+ | 'q'? ws s:r64 ws? ',' ws? d:r64 { $$ = INSTR2(11, s, d); }
mov = "mov" (
args:imm-rm-opargs { $$ = args; }
- | args:r-rm-opargs { args.instr.variant += 8; $$ = args; }
-) { $$.instr.kind = ASM_MOV; }
+ | args:r-rm-opargs { args.instr2.variant += 8; $$ = args; }
+) { $$.instr2.kind = ASM_MOV; }
xchg =
'xchg' (
- 'w'? ws s:ax ws? ',' ws? d:r16 { $$ = INSTR(0, s, d); }
- | 'w'? ws s:r16 ws? ',' ws? d:ax { $$ = INSTR(1, s, d); }
- | 'l'? ws s:eax ws? ',' ws? d:r32 { $$ = INSTR(2, s, d); }
- | 'l'? ws s:r32 ws? ',' ws? d:eax { $$ = INSTR(3, s, d); }
- | 'q'? ws s:rax ws? ',' ws? d:r64 { $$ = INSTR(4, s, d); }
- | 'q'? ws s:r64 ws? ',' ws? d:rax { $$ = INSTR(5, s, d); }
- | args:r-rm-opargs { args.instr.variant += 6; $$ = args; }
- ) { $$.instr.kind = ASM_XCHG; }
-
-add = "add" a:basic-op-args { a.instr.kind = ASM_ADD; $$ = a; }
-and = "and" a:basic-op-args { a.instr.kind = ASM_AND; $$ = a; }
-or = "or" a:basic-op-args { a.instr.kind = ASM_OR; $$ = a; }
-sub = "sub" a:basic-op-args { a.instr.kind = ASM_SUB; $$ = a; }
-xor = "xor" a:basic-op-args { a.instr.kind = ASM_XOR; $$ = a; }
+ 'w'? ws s:ax ws? ',' ws? d:r16 { $$ = INSTR2(0, s, d); }
+ | 'w'? ws s:r16 ws? ',' ws? d:ax { $$ = INSTR2(1, s, d); }
+ | 'l'? ws s:eax ws? ',' ws? d:r32 { $$ = INSTR2(2, s, d); }
+ | 'l'? ws s:r32 ws? ',' ws? d:eax { $$ = INSTR2(3, s, d); }
+ | 'q'? ws s:rax ws? ',' ws? d:r64 { $$ = INSTR2(4, s, d); }
+ | 'q'? ws s:r64 ws? ',' ws? d:rax { $$ = INSTR2(5, s, d); }
+ | args:r-rm-opargs { args.instr2.variant += 6; $$ = args; }
+ ) { $$.instr2.kind = ASM_XCHG; }
+
+add = "add" a:basic-op-args { a.instr2.kind = ASM_ADD; $$ = a; }
+and = "and" a:basic-op-args { a.instr2.kind = ASM_AND; $$ = a; }
+or = "or" a:basic-op-args { a.instr2.kind = ASM_OR; $$ = a; }
+sub = "sub" a:basic-op-args { a.instr2.kind = ASM_SUB; $$ = a; }
+xor = "xor" a:basic-op-args { a.instr2.kind = ASM_XOR; $$ = a; }
basic-op-args =
- 'b'? ws s:imm8 ws? ',' ws? d:al { $$ = INSTR(0, s, d); }
- | 'w'? ws s:imm16 ws? ',' ws? d:ax { $$ = INSTR(1, s, d); }
- | 'l'? ws s:imm32 ws? ',' ws? d:eax { $$ = INSTR(2, s, d); }
- | 'q'? ws s:imm32 ws? ',' ws? d:rax { $$ = INSTR(3, s, d); }
- | args:imm-rm-opargs { args.instr.variant += 4; $$ = args; }
- | args:r-rm-opargs { args.instr.variant += 12; $$ = args; }
+ 'b'? ws s:imm8 ws? ',' ws? d:al { $$ = INSTR2(0, s, d); }
+ | 'w'? ws s:imm16 ws? ',' ws? d:ax { $$ = INSTR2(1, s, d); }
+ | 'l'? ws s:imm32 ws? ',' ws? d:eax { $$ = INSTR2(2, s, d); }
+ | 'q'? ws s:imm32 ws? ',' ws? d:rax { $$ = INSTR2(3, s, d); }
+ | args:imm-rm-opargs { args.instr2.variant += 4; $$ = args; }
+ | args:r-rm-opargs { args.instr2.variant += 12; $$ = args; }
r64-or-rip = (
r:r64
diff --git a/main.c b/main.c
index 191d1d5..28e0e45 100644
--- a/main.c
+++ b/main.c
@@ -129,21 +129,6 @@ Relocation *newreloc() {
return &relocs[nrelocs++];
}
-static Parsev *dupv(Parsev *p) {
- Parsev *r = xmalloc(sizeof(Parsev));
- *r = *p;
- return r;
-}
-
-#define INSTR(V, S, D) \
- (Parsev) { \
- .instr = (Instr) { \
- .kind = 0, .variant = V, .src = dupv(&S), .dst = dupv(&D) \
- } \
- }
-#define REG(K) \
- (Parsev) { .kind = K }
-
static String decodestring(char *s) {
int i;
char *end;
@@ -185,6 +170,26 @@ static String decodestring(char *s) {
return (String){.kind = ASM_STRING, .len = len, .data = data};
}
+static Parsev *dupv(Parsev *p) {
+ Parsev *r = xmalloc(sizeof(Parsev));
+ *r = *p;
+ return r;
+}
+
+#define INSTR1(V, A) \
+ (Parsev) { \
+ .instr1 = (Instr1) { .kind = 0, .variant = V, .arg = dupv(&A), } \
+ }
+
+#define INSTR2(V, S, D) \
+ (Parsev) { \
+ .instr2 = (Instr2) { \
+ .kind = 0, .variant = V, .src = dupv(&S), .dst = dupv(&D) \
+ } \
+ }
+#define REG(K) \
+ (Parsev) { .kind = K }
+
#define YYSTYPE Parsev
#define YY_CTX_LOCAL
#define YY_CTX_MEMBERS Parsev v;
@@ -278,9 +283,9 @@ static uint8_t sibbyte(uint8_t ss, uint8_t idx, uint8_t base) {
}
/* Assemble op +rw | op + rd. */
-static void assembleplusr(uint8_t opcode, AsmKind reg) {
+static void assembleplusr(uint8_t opcode, uint8_t rexw, AsmKind reg) {
uint8_t bits = regbits(reg);
- uint8_t rex = rexbyte(isreg64(reg), 0, 0, bits & (1 << 3));
+ uint8_t rex = rexbyte(rexw, 0, 0, bits & (1 << 3));
if (isreg16(reg))
sb(0x66);
if (rex != rexbyte(0, 0, 0, 0))
@@ -355,7 +360,7 @@ static void assemblemem(Memarg *memarg, uint8_t rexw, uint8_t opcode,
sb2(opcode, modregrm(0, reg, rm));
}
} else {
- /* XXX choose smaller size if not label .*/
+ /* TODO choose smaller size if not label .*/
if ((rm & 7) == 4) { /* Matches '(%rsp/%esp...)'. */
sb3(opcode, modregrm(2, reg, 4), sibbyte(0, 4, 4));
} else if ((rm & 7) == 5) { /* Matches '(%rbp/%ebp...)'. */
@@ -368,7 +373,7 @@ static void assemblemem(Memarg *memarg, uint8_t rexw, uint8_t opcode,
}
/* Assemble op + imm -> r/m. */
-static void assembleimmrm(Instr *instr, uint8_t opcode, uint8_t immreg,
+static void assembleimmrm(Instr2 *instr, uint8_t opcode, uint8_t immreg,
uint8_t opsz) {
Imm *imm;
@@ -395,11 +400,20 @@ static void assembleimmrm(Instr *instr, uint8_t opcode, uint8_t immreg,
}
/* Assemble op + r <-> r/m. */
-static void assemblerrm(Instr *instr, uint8_t opcode, uint8_t opsz) {
+static void assemblerrm(Instr2 *instr, uint8_t opcode, uint8_t opsz) {
Memarg *memarg;
AsmKind regarg;
- if (instr->src->kind == ASM_MEMARG) {
+ if (instr->src->kind == ASM_MEMARG && instr->src->memarg.reg == ASM_RIP) {
+ memarg = &instr->src->memarg;
+ regarg = instr->dst->kind;
+ assembleriprel(memarg, isreg64(regarg), opcode, regbits(regarg), opsz);
+ } else if (instr->dst->kind == ASM_MEMARG &&
+ instr->dst->memarg.reg == ASM_RIP) {
+ memarg = &instr->dst->memarg;
+ regarg = instr->src->kind;
+ assembleriprel(memarg, isreg64(regarg), opcode, regbits(regarg), opsz);
+ } else if (instr->src->kind == ASM_MEMARG) {
memarg = &instr->src->memarg;
regarg = instr->dst->kind;
assemblemem(memarg, isreg64(regarg), opcode, regbits(regarg), opsz);
@@ -423,7 +437,7 @@ static void assemblerrm(Instr *instr, uint8_t opcode, uint8_t opsz) {
}
/* Assemble a 'basic op' which is just a repeated op pattern we have named. */
-static void assemblebasicop(Instr *instr, uint8_t opcode, uint8_t immreg) {
+static void assemblebasicop(Instr2 *instr, uint8_t opcode, uint8_t immreg) {
Imm *imm;
uint8_t opsz = 1 << (instr->variant % 4);
if (instr->variant < 4) {
@@ -441,21 +455,21 @@ static void assemblebasicop(Instr *instr, uint8_t opcode, uint8_t immreg) {
}
}
-static void assemblexchg(Instr *xchg) {
+static void assemblexchg(Instr2 *xchg) {
static uint8_t variant2op[18] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
0x86, 0x87, 0x87, 0x87, 0x86, 0x87,
0x87, 0x87, 0x86, 0x87, 0x87, 0x87};
uint8_t opcode = variant2op[xchg->variant];
if (xchg->variant < 6) {
- assembleplusr(opcode,
- (xchg->variant % 2) ? xchg->src->kind : xchg->dst->kind);
+ AsmKind reg = (xchg->variant % 2) ? xchg->src->kind : xchg->dst->kind;
+ assembleplusr(opcode, isreg64(reg), reg);
} else {
uint8_t opsz = 1 << ((xchg->variant - 6) % 4);
assemblerrm(xchg, opcode, opsz);
}
}
-static void assemblemov(Instr *mov) {
+static void assemblemov(Instr2 *mov) {
Imm *imm;
uint8_t opcode, rex, mod, rm;
@@ -467,7 +481,7 @@ static void assemblemov(Instr *mov) {
opcode = variant2op[mov->variant];
if (mov->variant >= 4 && mov->variant <= 6) {
imm = &mov->src->imm;
- assembleplusr(opcode, mov->dst->kind);
+ assembleplusr(opcode, isreg64(mov->dst->kind), mov->dst->kind);
assemblevalue(imm->l, imm->c, imm->nbytes);
} else if (mov->variant == 7 || mov->variant < 4) {
uint8_t opsz = 1 << (mov->variant % 4);
@@ -528,6 +542,48 @@ static void assemble(void) {
lfatal("%s already defined", sym->name);
sym->defined = 1;
break;
+ case ASM_CALL: {
+ Symbol *sym;
+ Relocation *reloc;
+
+ sb(0xe8);
+ sym = getsym(v->call.target);
+ reloc = newreloc();
+ reloc->kind = 0; // XXX
+ reloc->section = cursection;
+ reloc->sym = sym;
+ reloc->offset = cursection->hdr.sh_size;
+ sl(0);
+ break;
+ }
+ case ASM_JMP: {
+ Symbol *sym;
+ Relocation *reloc;
+
+ sb(0xe9);
+ sym = getsym(v->jmp.target);
+ reloc = newreloc();
+ reloc->kind = 0; // XXX
+ reloc->section = cursection;
+ reloc->sym = sym;
+ reloc->offset = cursection->hdr.sh_size;
+ sl(-4);
+ break;
+ }
+ case ASM_PUSH:
+ if (v->instr1.arg->kind == ASM_MEMARG) {
+ assemblemem(&v->instr1.arg->memarg, 0, 0xff, 0x06, 8);
+ } else {
+ assembleplusr(0x50, 0, v->instr1.arg->kind);
+ }
+ break;
+ case ASM_POP:
+ if (v->instr1.arg->kind == ASM_MEMARG) {
+ assemblemem(&v->instr1.arg->memarg, 0, 0x8f, 0x00, 8);
+ } else {
+ assembleplusr(0x58, 0, v->instr1.arg->kind);
+ }
+ break;
case ASM_NOP:
sb(0x90);
break;
@@ -538,12 +594,12 @@ static void assemble(void) {
sb(0xc3);
break;
case ASM_LEA: {
- uint8_t opsz = 1 << (v->instr.variant + 1);
- assemblerrm(&v->instr, 0x8d, opsz);
+ uint8_t opsz = 1 << (v->instr2.variant + 1);
+ assemblerrm(&v->instr2, 0x8d, opsz);
break;
}
case ASM_MOV:
- assemblemov(&v->instr);
+ assemblemov(&v->instr2);
break;
case ASM_ADD: {
static uint8_t variant2op[24] = {
@@ -551,7 +607,7 @@ static void assemble(void) {
0x80, 0x81, 0x81, 0x81, 0x02, 0x03, 0x03, 0x03,
0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01,
};
- assemblebasicop(&v->instr, variant2op[v->instr.variant], 0x00);
+ assemblebasicop(&v->instr2, variant2op[v->instr2.variant], 0x00);
break;
}
case ASM_AND: {
@@ -560,7 +616,7 @@ static void assemble(void) {
0x80, 0x81, 0x81, 0x81, 0x22, 0x23, 0x23, 0x23,
0x20, 0x21, 0x21, 0x21, 0x20, 0x21, 0x21, 0x21,
};
- assemblebasicop(&v->instr, variant2op[v->instr.variant], 0x04);
+ assemblebasicop(&v->instr2, variant2op[v->instr2.variant], 0x04);
break;
}
case ASM_OR: {
@@ -569,7 +625,7 @@ static void assemble(void) {
0x80, 0x81, 0x81, 0x81, 0x0a, 0x0b, 0x0b, 0x0b,
0x08, 0x09, 0x09, 0x09, 0x08, 0x09, 0x09, 0x09,
};
- assemblebasicop(&v->instr, variant2op[v->instr.variant], 0x01);
+ assemblebasicop(&v->instr2, variant2op[v->instr2.variant], 0x01);
break;
}
case ASM_SUB: {
@@ -578,7 +634,7 @@ static void assemble(void) {
0x80, 0x81, 0x81, 0x81, 0x2a, 0x2b, 0x2b, 0x2b,
0x28, 0x29, 0x29, 0x29, 0x28, 0x29, 0x29, 0x29,
};
- assemblebasicop(&v->instr, variant2op[v->instr.variant], 0x05);
+ assemblebasicop(&v->instr2, variant2op[v->instr2.variant], 0x05);
break;
}
case ASM_XOR: {
@@ -587,25 +643,11 @@ static void assemble(void) {
0x80, 0x81, 0x81, 0x81, 0x32, 0x33, 0x33, 0x33,
0x30, 0x31, 0x31, 0x31, 0x30, 0x31, 0x31, 0x31,
};
- assemblebasicop(&v->instr, variant2op[v->instr.variant], 0x06);
+ assemblebasicop(&v->instr2, variant2op[v->instr2.variant], 0x06);
break;
}
case ASM_XCHG: {
- assemblexchg(&v->instr);
- break;
- }
- case ASM_JMP: {
- Symbol *sym;
- Relocation *reloc;
-
- sb(0xe9);
- sym = getsym(v->jmp.target);
- reloc = newreloc();
- reloc->kind = 0; // XXX
- reloc->section = cursection;
- reloc->sym = sym;
- reloc->offset = cursection->hdr.sh_size;
- sl(-4);
+ assemblexchg(&v->instr2);
break;
}
default:
@@ -618,15 +660,22 @@ static void addtosymtab(Symbol *sym) {
Elf64_Sym elfsym;
int stype;
int sbind;
- stype = (sym->section->hdr.sh_flags & SHF_EXECINSTR) ? STT_FUNC : STT_OBJECT;
- sbind = sym->global ? STB_GLOBAL : STB_LOCAL;
+
+ if (sym->defined) {
+ stype =
+ (sym->section->hdr.sh_flags & SHF_EXECINSTR) ? STT_FUNC : STT_OBJECT;
+ sbind = sym->global ? STB_GLOBAL : STB_LOCAL;
+ } else {
+ stype = 0;
+ sbind = 0;
+ }
memset(&elfsym, 0, sizeof(elfsym));
elfsym.st_name = elfstr(strtab, sym->name);
elfsym.st_size = sym->size;
elfsym.st_value = sym->offset;
elfsym.st_info = ELF32_ST_BIND(sbind) | ELF32_ST_TYPE(stype);
- elfsym.st_shndx = sym->section->idx;
+ elfsym.st_shndx = sym->section ? sym->section->idx : SHN_UNDEF;
secaddbytes(symtab, (uint8_t *)&elfsym, sizeof(Elf64_Sym));
}
@@ -634,21 +683,12 @@ static void fillsymtab(void) {
Symbol *sym;
size_t i;
- // Local symbols
- for (i = 0; i < symbols->cap; i++) {
- if (!symbols->keys[i].str)
- continue;
- sym = symbols->vals[i];
- if (sym->global || !sym->section)
- continue;
- addtosymtab(sym);
- }
// Global symbols
for (i = 0; i < symbols->cap; i++) {
if (!symbols->keys[i].str)
continue;
sym = symbols->vals[i];
- if (!sym->global || !sym->section)
+ if (!sym->global && sym->defined)
continue;
addtosymtab(sym);
}
diff --git a/minias.h b/minias.h
index d005c2a..bc757d4 100644
--- a/minias.h
+++ b/minias.h
@@ -57,6 +57,9 @@ typedef enum {
// Instructions
ASM_NOP,
ASM_RET,
+ ASM_PUSH,
+ ASM_POP,
+ ASM_CALL,
ASM_JMP,
ASM_LEAVE,
ASM_ADD,
@@ -203,14 +206,25 @@ typedef String Asciiz;
typedef struct {
AsmKind kind;
const char *target;
+} Call;
+
+typedef struct {
+ AsmKind kind;
+ const char *target;
} Jmp;
typedef struct {
AsmKind kind;
uint8_t variant;
+ Parsev *arg;
+} Instr1;
+
+typedef struct {
+ AsmKind kind;
+ uint8_t variant;
Parsev *src;
Parsev *dst;
-} Instr;
+} Instr2;
union Parsev {
AsmKind kind;
@@ -220,7 +234,9 @@ union Parsev {
Ascii ascii;
Asciiz asciiz;
Memarg memarg;
- Instr instr;
+ Instr1 instr1;
+ Instr2 instr2;
+ Call call;
Jmp jmp;
Byte byte;
Imm imm;
diff --git a/test/test.sh b/test/test.sh
index e8293a7..1a3f34a 100644
--- a/test/test.sh
+++ b/test/test.sh
@@ -30,6 +30,14 @@ t () {
echo -n "."
}
+t "pushq (%r9)"
+t "pushq %r9"
+t "pushq %rax"
+t "popq (%r9)"
+t "popq %r9"
+t "popq %rax"
+
+
t "movb \$127, (%rsp)"
t "movb \$127, (%rbp)"
t "movb \$127, 2147483647(%rsp)"
@@ -87,6 +95,8 @@ do
t "${op}q \$2147483647, %r${r}x"
# r rm variants
+ t "${op}b (%rip), %${r}l"
+ t "${op}b (%rax), %${r}l"
t "${op}b (%rax), %${r}l"
t "${op}w (%rax), %${r}x"
t "${op}l (%rax), %e${r}x"
@@ -94,6 +104,7 @@ do
t "${op}q (%rbp), %r${r}x"
t "${op}q (%r8), %r${r}x"
t "${op}q (%r13), %r${r}x"
+ t "${op}b %${r}l, (%rip)"
t "${op}b %${r}l, (%rax)"
t "${op}w %${r}x, (%rax)"
t "${op}l %e${r}x, (%rax)"