aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Chambers <[email protected]>2021-10-19 16:15:49 +1300
committerAndrew Chambers <[email protected]>2021-10-19 16:15:49 +1300
commit221b83997a22fc2abc2282d90763e0435943021c (patch)
tree7e89cee98dad066e3d0de4204e21adead95c4dde
parent375efafb6aeb486ff2b079e8464d4b746ba4f213 (diff)
Remove special case for call.
-rw-r--r--asm.peg7
-rw-r--r--main.c47
-rw-r--r--minias.h12
-rw-r--r--parse.c10
4 files changed, 31 insertions, 45 deletions
diff --git a/asm.peg b/asm.peg
index 39c5d0e..089bfb2 100644
--- a/asm.peg
+++ b/asm.peg
@@ -134,11 +134,12 @@ instr =
call = "call" 'q'? ws (
'*' t:mem
- { $$.call = (Call){ .kind = ASM_CALL, .target.indirect=internparsev(&t), .indirect=1 } ; }
+ { $$ = OPMEM({.w=0}, -1, 0xff, 0x02, t); }
| '*' t:r64
- { $$.call = (Call){ .kind = ASM_CALL, .target.indirect=internparsev(&t), .indirect=1 } ; }
+ { $$ = OPREG({.w=0}, -1, 0xff, 0x02, t); }
| t:value
- { $$.call = (Call){ .kind = ASM_CALL, .target.direct=t.value, .indirect=0 } ; }
+ { Parsev ma = (Parsev){.memarg = (Memarg) {.kind=ASM_MEMARG, .disp = t.value }};
+ $$ = RELCALL({.w=0}, -1, 0xe8, ma); }
)
jmp = 'j' v:jmp-variant ws t:ident
diff --git a/main.c b/main.c
index f12ece5..8713b0c 100644
--- a/main.c
+++ b/main.c
@@ -481,30 +481,6 @@ assemblemem(const Memarg* memarg, Rex rex, VarBytes prefix, VarBytes opcode,
}
static void
-assemblecall(const Call* call)
-{
- Rex rex;
- uint8_t rm;
-
- if (call->indirect) {
- if (call->target.indirect->kind == ASM_MEMARG) {
- rex = (Rex){0};
- assemblemem(&call->target.indirect->memarg, rex, -1, 0xff, 0x02, 0);
- } else {
- rm = regbits(call->target.indirect->kind);
- rex = (Rex){ .b = !!(rm & (1 << 3)) };
- assemblerex(rex);
- assemblevbytes(0xff);
- sb(modregrmbyte(0x03, 0x02, rm));
- }
- } else {
- sb(0xe8);
- assemblereloc(
- call->target.direct.l, call->target.direct.c - 4, 4, R_X86_64_PC32);
- }
-}
-
-static void
assemblejmp(const Jmp* j)
{
int jmpsize;
@@ -550,16 +526,20 @@ assemblejmp(const Jmp* j)
static void
assembleabsimm(const Imm* imm)
{
+ int reltype;
+
if (imm->nbytes == 1)
- assemblereloc(imm->v.l, imm->v.c, imm->nbytes, R_X86_64_8);
+ reltype = R_X86_64_8;
else if (imm->nbytes == 2)
- assemblereloc(imm->v.l, imm->v.c, imm->nbytes, R_X86_64_16);
+ reltype = R_X86_64_16;
else if (imm->nbytes == 4)
- assemblereloc(imm->v.l, imm->v.c, imm->nbytes, R_X86_64_32);
+ reltype = R_X86_64_32;
else if (imm->nbytes == 8)
- assemblereloc(imm->v.l, imm->v.c, imm->nbytes, R_X86_64_64);
+ reltype = R_X86_64_64;
else
unreachable();
+
+ assemblereloc(imm->v.l, imm->v.c, imm->nbytes, reltype);
}
static void
@@ -618,6 +598,14 @@ assembleinstr(const Instr* instr)
assemblevbytes(instr->opcode);
assembleabsimm(imm);
break;
+ case ENCODER_RELCALL:
+ memarg = &instr->arg1->memarg;
+ rex = instr->rex;
+ assemblevbytes(instr->prefix);
+ assemblerex(rex);
+ assemblevbytes(instr->opcode);
+ assemblereloc(memarg->disp.l, memarg->disp.c - 4, 4, R_X86_64_PC32);
+ break;
case ENCODER_IMMREG:
imm = &instr->arg1->imm;
reg = instr->fixedreg;
@@ -821,9 +809,6 @@ assemble(void)
case ASM_INSTR:
assembleinstr(&v->instr);
break;
- case ASM_CALL:
- assemblecall(&v->call);
- break;
case ASM_JMP:
assemblejmp(&v->jmp);
break;
diff --git a/minias.h b/minias.h
index ec8f7cc..1baaf89 100644
--- a/minias.h
+++ b/minias.h
@@ -61,7 +61,6 @@ typedef enum {
ASM_DIR_QUAD,
ASM_DIR_BALIGN,
// Instructions.
- ASM_CALL,
ASM_JMP,
ASM_INSTR,
// Registers, order matters.
@@ -237,15 +236,6 @@ typedef struct String {
typedef String Ascii;
typedef String Asciiz;
-typedef struct Call {
- AsmKind kind;
- uint32_t indirect;
- union {
- const Parsev* indirect;
- Value direct;
- } target;
-} Call;
-
typedef struct Jmp {
AsmKind kind;
uint32_t cc; /* 0 means unconditional. */
@@ -267,6 +257,7 @@ typedef enum Encoder {
ENCODER_OP,
ENCODER_OPREG,
ENCODER_OPMEM,
+ ENCODER_RELCALL,
ENCODER_R,
ENCODER_RIMM,
ENCODER_IMM,
@@ -305,7 +296,6 @@ union Parsev {
Asciiz asciiz;
Memarg memarg;
Instr instr;
- Call call;
Jmp jmp;
Fill fill;
Byte dirbyte;
diff --git a/parse.c b/parse.c
index 3137447..da01509 100644
--- a/parse.c
+++ b/parse.c
@@ -168,6 +168,16 @@ needsmovabs(Imm* imm)
} \
}
+#define RELCALL(REX, PREFIX, OPCODE, A1) \
+ (Parsev) \
+ { \
+ .instr = (Instr) \
+ { \
+ .kind = ASM_INSTR, .encoder = ENCODER_RELCALL, .prefix = PREFIX, \
+ .opcode = OPCODE, .rex = (Rex)REX, .arg1 = internparsev(&A1), \
+ } \
+ }
+
#define IMMREG(REX, PREFIX, OPCODE, IMMREG, A1, A2) \
(Parsev) \
{ \