From 221b83997a22fc2abc2282d90763e0435943021c Mon Sep 17 00:00:00 2001 From: Andrew Chambers Date: Tue, 19 Oct 2021 16:15:49 +1300 Subject: Remove special case for call. --- asm.peg | 7 ++++--- main.c | 47 ++++++++++++++++------------------------------- minias.h | 12 +----------- parse.c | 10 ++++++++++ 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 @@ -480,30 +480,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) { @@ -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) \ { \ -- cgit v1.2.3