aboutsummaryrefslogtreecommitdiff
path: root/i386-gen.c
diff options
context:
space:
mode:
authorbellard <bellard>2002-11-03 00:43:01 +0000
committerbellard <bellard>2002-11-03 00:43:01 +0000
commitfde824b7cd22a78bb2cb171ab16abafa8135c233 (patch)
tree38d8602005136cbd2fbcce3aad79d59c0af8454d /i386-gen.c
parentbde35a81f30270ea61a8bb9cb96bfd8614bc8353 (diff)
downloadtinycc-fde824b7cd22a78bb2cb171ab16abafa8135c233.tar.gz
tinycc-fde824b7cd22a78bb2cb171ab16abafa8135c233.tar.bz2
handle computed gotos
Diffstat (limited to 'i386-gen.c')
-rw-r--r--i386-gen.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/i386-gen.c b/i386-gen.c
index e32b965..1fb27e4 100644
--- a/i386-gen.c
+++ b/i386-gen.c
@@ -349,9 +349,8 @@ static void gadd_sp(int val)
}
}
-/* generate function call with address in (vtop->t, vtop->c) and free function
- context. Stack entry is popped */
-void gfunc_call(GFuncContext *c)
+/* 'is_jmp' is '1' if it is a jump */
+static void gcall_or_jmp(int is_jmp)
{
int r;
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
@@ -365,13 +364,20 @@ void gfunc_call(GFuncContext *c)
put_elf_reloc(symtab_section, cur_text_section,
ind + 1, R_386_PC32, 0);
}
- oad(0xe8, vtop->c.ul - 4);
+ oad(0xe8 + is_jmp, vtop->c.ul - 4); /* call/jmp im */
} else {
/* otherwise, indirect call */
r = gv(RC_INT);
- o(0xff); /* call *r */
- o(0xd0 + r);
+ o(0xff); /* call/jmp *r */
+ o(0xd0 + r + (is_jmp << 4));
}
+}
+
+/* generate function call with address in (vtop->t, vtop->c) and free function
+ context. Stack entry is popped */
+void gfunc_call(GFuncContext *c)
+{
+ gcall_or_jmp(0);
if (c->args_size && c->func_call == FUNC_CDECL)
gadd_sp(c->args_size);
vtop--;
@@ -862,6 +868,13 @@ void gen_cvt_ftof(int t)
gv(RC_FLOAT);
}
+/* computed goto support */
+void ggoto(void)
+{
+ gcall_or_jmp(1);
+ vtop--;
+}
+
/* bound check support functions */
#ifdef CONFIG_TCC_BCHECK