aboutsummaryrefslogtreecommitdiff
path: root/i386-gen.c
diff options
context:
space:
mode:
Diffstat (limited to 'i386-gen.c')
-rw-r--r--i386-gen.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/i386-gen.c b/i386-gen.c
index 044f9e6..9ff2e18 100644
--- a/i386-gen.c
+++ b/i386-gen.c
@@ -43,6 +43,7 @@ enum {
TREG_ECX,
TREG_EDX,
TREG_ST0,
+ TREG_ESP = 4
};
/* return registers for function */
@@ -1117,6 +1118,44 @@ ST_FUNC void gen_bounded_ptr_deref(void)
}
#endif
+/* Save the stack pointer onto the stack */
+ST_FUNC void gen_vla_sp_save(int addr) {
+ /* mov %esp,addr(%ebp)*/
+ o(0x89);
+ gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr);
+}
+
+/* Restore the SP from a location on the stack */
+ST_FUNC void gen_vla_sp_restore(int addr) {
+ o(0x8b);
+ gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr);
+}
+
+/* Subtract from the stack pointer, and push the resulting value onto the stack */
+ST_FUNC void gen_vla_alloc(CType *type, int align) {
+#ifdef TCC_TARGET_PE
+ /* alloca does more than just adjust %rsp on Windows */
+ vpush_global_sym(&func_old_type, TOK_alloca);
+ vswap(); /* Move alloca ref past allocation size */
+ gfunc_call(1);
+ vset(type, REG_IRET, 0);
+#else
+ int r;
+ r = gv(RC_INT); /* allocation size */
+ /* sub r,%rsp */
+ o(0x2b);
+ o(0xe0 | r);
+ /* We align to 16 bytes rather than align */
+ /* and ~15, %esp */
+ o(0xf0e483);
+ /* mov %esp, r */
+ o(0x89);
+ o(0xe0 | r);
+ vpop();
+ vset(type, r, 0);
+#endif
+}
+
/* end of X86 code generator */
/*************************************************************/
#endif