aboutsummaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorAndrew Chambers <[email protected]>2021-10-12 19:42:01 +1300
committerAndrew Chambers <[email protected]>2021-10-12 19:42:01 +1300
commit25fa3f8e631f26b09303b1263d9bf5cf4e564c64 (patch)
treef3abf4d65645c5f1327dd81a9af8249f95dcc1bb /main.c
parentb4e630f77661aae9e030e9dabead9ba5b0370368 (diff)
More types of call.
Diffstat (limited to 'main.c')
-rw-r--r--main.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/main.c b/main.c
index ffd925f..8ba72e2 100644
--- a/main.c
+++ b/main.c
@@ -426,6 +426,21 @@ static void assemblemem(Memarg *memarg, uint8_t rexw, VarBytes prefix,
uint8_t rex, mod, rm, scale, index, base, sib;
+ /* Direct memory access */
+ if (memarg->base == ASM_NO_REG) {
+ mod = 0;
+ rm = 4;
+ rex = rexbyte(rexw, reg & (1 << 3), 0, 0);
+ assemblemodregrm(rex, prefix, opcode, mod, reg, rm);
+ sb(sibbyte(0, 4, 5));
+ if (memarg->disp.l) {
+ assemblereloc(memarg->disp.l, memarg->disp.c, 4, R_X86_64_PC32);
+ } else {
+ assembleconstant(memarg->disp.c, 4);
+ }
+ return;
+ }
+
/* rip relative addressing. */
if (memarg->base == ASM_RIP) {
rm = 0x05;
@@ -821,11 +836,22 @@ static void assemble(void) {
sym->defined = 1;
break;
case ASM_CALL: {
- Symbol *sym;
- Relocation *reloc;
-
- sb(0xe8);
- assemblereloc(v->call.target, -4, 4, R_X86_64_PC32);
+ uint8_t rm, rex;
+
+ if (v->call.indirect) {
+ if (v->call.target.indirect->kind == ASM_MEMARG) {
+ assemblemem(&v->call.target.indirect->memarg, 0, EMPTY_VBYTES, 0xff,
+ 0x02);
+ } else {
+ rm = regbits(v->call.target.indirect->kind);
+ rex = rexbyte(0, 0, 0, rm & (1 << 3));
+ assemblemodregrm(rex, EMPTY_VBYTES, 0xff, 0x03, 0x02, rm);
+ }
+ } else {
+ sb(0xe8);
+ assemblereloc(v->call.target.direct.l, v->call.target.direct.c - 4, 4,
+ R_X86_64_PC32);
+ }
break;
}
case ASM_JMP: {