diff options
| author | Andrew Chambers <[email protected]> | 2021-10-19 16:15:49 +1300 |
|---|---|---|
| committer | Andrew Chambers <[email protected]> | 2021-10-19 16:15:49 +1300 |
| commit | 221b83997a22fc2abc2282d90763e0435943021c (patch) | |
| tree | 7e89cee98dad066e3d0de4204e21adead95c4dde | |
| parent | 375efafb6aeb486ff2b079e8464d4b746ba4f213 (diff) | |
Remove special case for call.
| -rw-r--r-- | asm.peg | 7 | ||||
| -rw-r--r-- | main.c | 47 | ||||
| -rw-r--r-- | minias.h | 12 | ||||
| -rw-r--r-- | parse.c | 10 |
4 files changed, 31 insertions, 45 deletions
@@ -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 @@ -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; @@ -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; @@ -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) \ { \ |
