Lhogho  0.0.028
 All Data Structures Files Functions Variables Typedefs Macros Pages
i386.c File Reference

Go to the source code of this file.

Macros

#define EXIT   (void*)ctx->exit_addr
 
#define START_IP   (ctx->generate?(int)MEMORY(ctx->generate):0)
 start IP More...
 
#define LOCAL_IP   (ctx->size)
 local IP (0-based) More...
 
#define IP   START_IP+LOCAL_IP
 current IP More...
 
#define REL(addr)   relative( ctx, (uint_t)addr )
 relative address More...
 
#define EMIT1(a)   emit_1(ctx,a)
 
#define EMIT2(a)   emit_2(ctx,a)
 
#define EMIT3(a, b)   emit_2(ctx,a); emit_1(ctx,b)
 
#define EMIT4(a)   emit_4(ctx,a)
 
#define EMIT5(a, b)   emit_1(ctx,a); emit_4(ctx,(uint_t)b)
 
#define EMIT6(a, b)   emit_2(ctx,a); emit_4(ctx,(uint_t)b)
 
#define PUSH_EAX   { EMIT1(0x50); INSTR("push eax"); }
 
#define PUSH_EDX   { EMIT1(0x52); INSTR("push edx"); }
 
#define PUSH_EBP   { EMIT1(0x55); INSTR("push ebp"); }
 
#define PUSH_ESI   { EMIT1(0x56); INSTR("push esi"); }
 
#define PUSH_EBX   { EMIT1(0x53); INSTR("push ebx"); }
 
#define POP_EAX   { EMIT1(0x58); INSTR("pop eax"); }
 
#define POP_EDX   { EMIT1(0x5A); INSTR("pop edx"); }
 
#define POP_EBP   { EMIT1(0x5D); INSTR("pop ebp"); }
 
#define POP_ESI   { EMIT1(0x5E); INSTR("pop esi"); }
 
#define POP_EBX   { EMIT1(0x5B); INSTR("pop ebx"); }
 
#define PUSH_MEM_EAX(ofs)   { EMIT6(0xB0FF,ofs); INSTR("push [eax%p]",ofs); }
 
#define PUSH_MEM_EBP(ofs)   { EMIT6(0xB5FF,ofs); INSTR("push [ebp%p]",ofs); }
 
#define PUSH_MEM_ESI(ofs)   { EMIT6(0xB6FF,ofs); INSTR("push [esi%p]",ofs); }
 
#define PUSH_MEM(ofs)   { EMIT6(0x35FF,ofs); INSTR("push [%d]",ofs); }
 
#define PUSH_SOURCE(s)   { EMIT5(0x68,s); INSTR("push (%l)",s); }
 
#define PUSH_CONST(n)   { EMIT5(0x68,n); INSTR("push %d",n); }
 
#define PUSH_ATOM(a)   { EMIT5(0x68,a); INSTR("push %a",a); }
 
#define PUSH_ATOMSTR(a, s)   { EMIT5(0x68,a); INSTR("push %s",s); }
 
#define MOV_EAX_ATOM(atom)   { EMIT5(0xB8,atom); INSTR("mov eax,%a",atom); }
 
#define MOV_ESI_CONST(n)   { EMIT5(0xBE,n); INSTR("mov esi,%d",n); }
 
#define MOV_ESI_CONST(n)   { EMIT5(0xBE,n); INSTR("mov esi,%d",n); }
 
#define MOV_EBX_CONST(n)   { EMIT5(0xBB,n); INSTR("mov ebx,%d",n); }
 
#define MOV_EAX_EBP   { EMIT2(0xE889); INSTR("mov eax,ebp"); }
 
#define MOV_EBP_ESP   { EMIT2(0xE589); INSTR("mov ebp,esp"); }
 
#define MOV_ESP_EBP   { EMIT2(0xEC89); INSTR("mov esp,ebp"); }
 
#define MOV_ESI_EBP   { EMIT2(0xEE89); INSTR("mov esi,ebp"); }
 
#define MOV_EAX_MEM_ESP   { EMIT3(0x048B,0x24); INSTR("mov eax,[esp]"); }
 
#define MOV_EAX_MEM_EBP(ofs)   { EMIT3(0x458B,ofs); INSTR("mov eax,[ebp%p]",ofs); }
 
#define MOV_EAX_MEM_EAX(ofs)   { EMIT3(0x408B,ofs); INSTR("mov eax,[eax%p]",ofs); }
 
#define MOV_EAX_MEM_OFS(ofs)   { EMIT6(0x058B,ofs); INSTR("mov eax,[%d]",ofs); }
 
#define MOV_EBP_MEM_OFS(ofs)   { EMIT6(0x2D8B,ofs); INSTR("mov ebp,[%d]",ofs); }
 
#define MOV_EBX_MEM_OFS(ofs)   { EMIT6(0x1D8B,ofs); INSTR("mov ebp,[%d]",ofs); }
 
#define MOV_MEM_EBP_EAX(ofs)   { EMIT6(0x8589,ofs); INSTR("mov [ebp%p],eax",ofs); }
 
#define MOV_MEM_ESI_EAX(ofs)   { EMIT6(0x8689,ofs); INSTR("mov [esi%p],eax",ofs); }
 
#define MOV_MEM_OFS_EAX(ofs)   { EMIT6(0x0589,ofs); INSTR("mov [%d],eax",ofs); }
 
#define MOV_MEM_OFS_EBP(ofs)   { EMIT6(0x2D89,ofs); INSTR("mov [%d],ebp",ofs); }
 
#define MOV_MEM_OFS_CONST(ofs, n)
 
#define MOV_ESI_SSMEM_ESI_4   { EMIT4(0xFC768B36); INSTR("mov esi,ss:[esi-4]"); }
 
#define MOV_ESI_SSMEM_EBP_4   { EMIT4(0xFC758B36); INSTR("mov esi,ss:[ebp-4]"); }
 
#define INC_EAX_MEM(n)   { EMIT3(0x40FF,n); INSTR("inc [eax%p]",n); }
 
#define DEC_EAX_MEM(n)   { EMIT3(0x48FF,n); INSTR("dec [eax%p]",n); }
 
#define RET   { EMIT1(0xC3); INSTR("ret"); }
 
#define ADD_EAX_CONST_4(n)   { EMIT5(0x05,n); INSTR("add eax,%d",n); }
 
#define ADD_ESI_CONST_4(n)   { EMIT6(0xC681,n); INSTR("add esi,%d",n); }
 
#define CMP_EBX_CONST(n)   { EMIT3(0xFB83,n); INSTR("cmp ebx,%d",n); }
 
#define CMP_EAX_CONST(n)   { EMIT5(0x3D,n); INSTR("cmp eax,%d",n); }
 
#define CMP_EAX_ATOM(a)   { EMIT5(0x3D,a); INSTR("cmp eax,%l",a); }
 
#define CMP_ID_ERROR
 
#define CMP_MEM_EBP(ofs, val)
 
#define CMP_MEM_OFS_CONST_4(ofs, n)   { EMIT6(0x3D81,ofs); EMIT4(n); INSTR("cmp [%d],%a", ofs, n); }
 
#define CMP_MEM_OFS_CONST_1(ofs, n)
 
#define JE_EXIT   { EMIT6(0x840F,REL(EXIT)); INSTR("je exit"); }
 
#define JE(addr, name)   { EMIT6(0x840F,REL(addr)); INSTR("je %s",name); }
 
#define JNE(addr, name)   { EMIT6(0x850F,REL(addr)); INSTR("jne %s",name); }
 
#define JNZ(addr, name)   { EMIT6(0x850F,REL(addr)); INSTR("jnz %s",name); }
 
#define JMP_EXIT   { EMIT5(0xE9,REL(EXIT)); INSTR("jmp exit"); }
 
#define JMP(addr, name)   { EMIT5(0xE9,REL(addr)); INSTR("jmp %s",name); }
 
#define JMP_ATOM(addr, name)   { EMIT5(0xE9,REL(addr)); INSTR("jmp %a",name); }
 
#define JMP_EAX(name)   { EMIT2(0xE0FF); INSTR("jmp %a",name); }
 
#define CALL(addr, name)   { EMIT5(0xE8,REL(addr)); INSTR("call %s",name); }
 
#define CALL_ATOM(addr, name)   { EMIT5(0xE8,REL(addr)); INSTR("call %a",name); }
 
#define CALL_MEM(addr, name)   { EMIT6(0x15FF,addr); INSTR("call [%a]",name); }
 
#define CALL_MEM_EAX(addr, name)   { EMIT6(0x90FF,addr); INSTR("call [eax+%s]",name); }
 
#define FSTPF_MEM_ESP   { EMIT2(0x1CD9); EMIT1(0x24); INSTR("fstpf [esp]"); }
 
#define FSTPD_MEM_ESP   { EMIT2(0x1CDD); EMIT1(0x24); INSTR("fstpd [esp]"); }
 
#define INT_3   { EMIT1(0xCC); INSTR("int 3"); }
 
#define NOP   { EMIT1(0x90); INSTR("nop"); }
 

Functions

uint_t relative (context_t *ctx, int addr)
 calculates relative offset More...
 
void asm_label (context_t *ctx, chars_t label)
 disassemble label More...
 
void asm_prologue (context_t *ctx, atom_t func, int check)
 generates a function prologue More...
 
void asm_preepilogue (context_t *ctx)
 
void asm_epilogue (context_t *ctx, atom_t func, int is_macro)
 generates a function epilogue More...
 
void asm_push_atom (context_t *ctx, atom_t atom)
 genarates a code to push atom More...
 
void asm_pop_atom (context_t *ctx)
 genarates a code to pop atom More...
 
void asm_pop_dummy (context_t *ctx)
 genarates a code to pop (and ignore) More...
 
void asm_push_result (context_t *ctx)
 genarates a code to push function's result More...
 
void asm_result_proc (context_t *ctx, atom_t source)
 check result of a command More...
 
void asm_result_unknown (context_t *ctx, atom_t source)
 check result of expression More...
 
void asm_result_func (context_t *ctx, atom_t source)
 check result of a function More...
 
int asm_static_link (context_t *ctx, atom_t var)
 generated code for static link More...
 
void compile_system_reference (context_t *ctx, atom_t name)
 compiles reference to system variable More...
 
void asm_reference (context_t *ctx, atom_t var, atom_t source, int check)
 generated code for reference More...
 
void asm_make_direct (context_t *ctx, atom_t var, atom_t source)
 generated code for direct make statement More...
 
void asm_push_value_addr (context_t *ctx, atom_t var)
 generated code for address of var's value More...
 
void asm_call_atom (context_t *ctx, atom_t var, int params)
 genarates a code to call atom More...
 
void asm_runtime_reference (context_t *ctx)
 genarates a code to get variable value More...
 
void asm_dump_source (context_t *ctx, atom_t source)
 dump current source More...
 
void asm_empty_body (context_t *ctx)
 generates the body of an empty function More...
 
void asm_output (context_t *ctx, atom_t source, int true_output)
 generated code for OUTPUT statement More...
 
void asm_stop (context_t *ctx, atom_t source)
 generated code for STOP statement More...
 
void asm_boolean (context_t *ctx, atom_t source)
 generated code for checking boolean values More...
 
int asm_if_prologue (context_t *ctx)
 generates prologue for IF command More...
 
int asm_if_epilogue (context_t *ctx)
 generates epilogue for IF command More...
 
void asm_fix (context_t *ctx, int addr)
 fixes unresolved offset More...
 
int asm_repeat_prologue_const (context_t *ctx, int cnt)
 generates const-prologue for REPEAT command More...
 
int asm_repeat_prologue_expr (context_t *ctx, atom_t source, int *branch2)
 generates expr-prologue for REPEAT command More...
 
void asm_repeat_epilogue (context_t *ctx, int branch, int branch2)
 generates epilogue for REPEAT command More...
 
int asm_forever_prologue (context_t *ctx)
 generates prologue for FOREVER command More...
 
void asm_forever_epilogue (context_t *ctx, int branch)
 generates epilogue for FOREVER command More...
 
void asm_push_frame (context_t *ctx)
 generates code to push frame pointer More...
 
void asm_pop_frame (context_t *ctx)
 generates code to pop frame pointer More...
 
void asm_push_mode (context_t *ctx, int mode)
 generates code to push mode More...
 
void asm_adjust_result (context_t *ctx)
 generated code for result adjustment More...
 
void asm_pop_result (context_t *ctx)
 generated code for result adjustment More...
 
int asm_while_prologue (context_t *ctx, int is_while, int is_do)
 generates prologue for WHILE command More...
 
int asm_while_inlogue (context_t *ctx, atom_t source, int is_while)
 generates inlogue for WHILE command More...
 
void asm_while_epilogue (context_t *ctx, int loop_branch, int skip_branch, int is_while)
 generates epilogue for WHILE/UNTIL command More...
 
void asm_set_output_status (context_t *ctx, int n)
 generates code for output status More...
 
int asm_catch_prologue (context_t *ctx)
 generates prologue for CATCH command More...
 
void asm_catch_epilogue (context_t *ctx)
 generates epilogue for CATCH command More...
 
void asm_goto (context_t *ctx, atom_t tag)
 generates jump to specific address More...
 
void asm_goto_prologue (context_t *ctx, atom_t source)
 generates prologue for GOTO command More...
 
void asm_goto_epilogue (context_t *ctx, atom_t source)
 generates epilogue for GOTO command More...
 
int asm_test_prologue (context_t *ctx, int criteria)
 generates prologue for IFTRUE/IFFALSE command More...
 
void asm_run_epilogue (context_t *ctx)
 generates epilogue for RUN command More...
 
void asm_runresult_epilogue (context_t *ctx)
 generates epilogue for RUNRESULT command More...
 
int asm_for_prologue (context_t *ctx, atom_t step_var, atom_t source, int *branch2)
 generates prologue for FOR command More...
 
void asm_for_epilogue (context_t *ctx, int branch, int branch2)
 generates epilogue for FOR command More...
 
void asm_external_function (context_t *ctx, atom_t func)
 generates trampoline to external function More...
 
void asm_internal_function (context_t *ctx, int static_link, atom_t func)
 generates trampoline to external function More...
 
void asm_int_3 (context_t *ctx)
 generates Interrupt 3 More...
 
void asm_nop (context_t *ctx)
 generates NOP More...
 

Macro Definition Documentation

#define EXIT   (void*)ctx->exit_addr

Definition at line 66 of file i386.c.

#define START_IP   (ctx->generate?(int)MEMORY(ctx->generate):0)

Definition at line 67 of file i386.c.

#define LOCAL_IP   (ctx->size)

Definition at line 68 of file i386.c.

#define IP   START_IP+LOCAL_IP

Definition at line 69 of file i386.c.

#define REL (   addr)    relative( ctx, (uint_t)addr )

Definition at line 70 of file i386.c.

#define EMIT1 (   a)    emit_1(ctx,a)

Definition at line 72 of file i386.c.

#define EMIT2 (   a)    emit_2(ctx,a)

Definition at line 73 of file i386.c.

#define EMIT3 (   a,
 
)    emit_2(ctx,a); emit_1(ctx,b)

Definition at line 74 of file i386.c.

#define EMIT4 (   a)    emit_4(ctx,a)

Definition at line 75 of file i386.c.

#define EMIT5 (   a,
 
)    emit_1(ctx,a); emit_4(ctx,(uint_t)b)

Definition at line 76 of file i386.c.

#define EMIT6 (   a,
 
)    emit_2(ctx,a); emit_4(ctx,(uint_t)b)

Definition at line 77 of file i386.c.

#define PUSH_EAX   { EMIT1(0x50); INSTR("push eax"); }

Definition at line 118 of file i386.c.

#define PUSH_EDX   { EMIT1(0x52); INSTR("push edx"); }

Definition at line 119 of file i386.c.

#define PUSH_EBP   { EMIT1(0x55); INSTR("push ebp"); }

Definition at line 120 of file i386.c.

#define PUSH_ESI   { EMIT1(0x56); INSTR("push esi"); }

Definition at line 121 of file i386.c.

#define PUSH_EBX   { EMIT1(0x53); INSTR("push ebx"); }

Definition at line 122 of file i386.c.

#define POP_EAX   { EMIT1(0x58); INSTR("pop eax"); }

Definition at line 124 of file i386.c.

#define POP_EDX   { EMIT1(0x5A); INSTR("pop edx"); }

Definition at line 125 of file i386.c.

#define POP_EBP   { EMIT1(0x5D); INSTR("pop ebp"); }

Definition at line 126 of file i386.c.

#define POP_ESI   { EMIT1(0x5E); INSTR("pop esi"); }

Definition at line 127 of file i386.c.

#define POP_EBX   { EMIT1(0x5B); INSTR("pop ebx"); }

Definition at line 128 of file i386.c.

#define PUSH_MEM_EAX (   ofs)    { EMIT6(0xB0FF,ofs); INSTR("push [eax%p]",ofs); }

Definition at line 130 of file i386.c.

#define PUSH_MEM_EBP (   ofs)    { EMIT6(0xB5FF,ofs); INSTR("push [ebp%p]",ofs); }

Definition at line 131 of file i386.c.

#define PUSH_MEM_ESI (   ofs)    { EMIT6(0xB6FF,ofs); INSTR("push [esi%p]",ofs); }

Definition at line 132 of file i386.c.

#define PUSH_MEM (   ofs)    { EMIT6(0x35FF,ofs); INSTR("push [%d]",ofs); }

Definition at line 134 of file i386.c.

#define PUSH_SOURCE (   s)    { EMIT5(0x68,s); INSTR("push (%l)",s); }

Definition at line 136 of file i386.c.

#define PUSH_CONST (   n)    { EMIT5(0x68,n); INSTR("push %d",n); }

Definition at line 137 of file i386.c.

#define PUSH_ATOM (   a)    { EMIT5(0x68,a); INSTR("push %a",a); }

Definition at line 138 of file i386.c.

#define PUSH_ATOMSTR (   a,
 
)    { EMIT5(0x68,a); INSTR("push %s",s); }

Definition at line 139 of file i386.c.

#define MOV_EAX_ATOM (   atom)    { EMIT5(0xB8,atom); INSTR("mov eax,%a",atom); }

Definition at line 141 of file i386.c.

#define MOV_ESI_CONST (   n)    { EMIT5(0xBE,n); INSTR("mov esi,%d",n); }

Definition at line 143 of file i386.c.

#define MOV_ESI_CONST (   n)    { EMIT5(0xBE,n); INSTR("mov esi,%d",n); }

Definition at line 143 of file i386.c.

#define MOV_EBX_CONST (   n)    { EMIT5(0xBB,n); INSTR("mov ebx,%d",n); }

Definition at line 144 of file i386.c.

#define MOV_EAX_EBP   { EMIT2(0xE889); INSTR("mov eax,ebp"); }

Definition at line 146 of file i386.c.

#define MOV_EBP_ESP   { EMIT2(0xE589); INSTR("mov ebp,esp"); }

Definition at line 147 of file i386.c.

#define MOV_ESP_EBP   { EMIT2(0xEC89); INSTR("mov esp,ebp"); }

Definition at line 148 of file i386.c.

#define MOV_ESI_EBP   { EMIT2(0xEE89); INSTR("mov esi,ebp"); }

Definition at line 149 of file i386.c.

#define MOV_EAX_MEM_ESP   { EMIT3(0x048B,0x24); INSTR("mov eax,[esp]"); }

Definition at line 151 of file i386.c.

#define MOV_EAX_MEM_EBP (   ofs)    { EMIT3(0x458B,ofs); INSTR("mov eax,[ebp%p]",ofs); }

Definition at line 152 of file i386.c.

#define MOV_EAX_MEM_EAX (   ofs)    { EMIT3(0x408B,ofs); INSTR("mov eax,[eax%p]",ofs); }

Definition at line 153 of file i386.c.

#define MOV_EAX_MEM_OFS (   ofs)    { EMIT6(0x058B,ofs); INSTR("mov eax,[%d]",ofs); }

Definition at line 154 of file i386.c.

#define MOV_EBP_MEM_OFS (   ofs)    { EMIT6(0x2D8B,ofs); INSTR("mov ebp,[%d]",ofs); }

Definition at line 155 of file i386.c.

#define MOV_EBX_MEM_OFS (   ofs)    { EMIT6(0x1D8B,ofs); INSTR("mov ebp,[%d]",ofs); }

Definition at line 156 of file i386.c.

#define MOV_MEM_EBP_EAX (   ofs)    { EMIT6(0x8589,ofs); INSTR("mov [ebp%p],eax",ofs); }

Definition at line 158 of file i386.c.

#define MOV_MEM_ESI_EAX (   ofs)    { EMIT6(0x8689,ofs); INSTR("mov [esi%p],eax",ofs); }

Definition at line 159 of file i386.c.

#define MOV_MEM_OFS_EAX (   ofs)    { EMIT6(0x0589,ofs); INSTR("mov [%d],eax",ofs); }

Definition at line 160 of file i386.c.

#define MOV_MEM_OFS_EBP (   ofs)    { EMIT6(0x2D89,ofs); INSTR("mov [%d],ebp",ofs); }

Definition at line 161 of file i386.c.

#define MOV_MEM_OFS_CONST (   ofs,
 
)
Value:
{EMIT6(0x05C7,ofs); EMIT4(n); \
INSTR("mov [%d],%a", ofs, n); }

Definition at line 162 of file i386.c.

#define MOV_ESI_SSMEM_ESI_4   { EMIT4(0xFC768B36); INSTR("mov esi,ss:[esi-4]"); }

Definition at line 165 of file i386.c.

#define MOV_ESI_SSMEM_EBP_4   { EMIT4(0xFC758B36); INSTR("mov esi,ss:[ebp-4]"); }

Definition at line 166 of file i386.c.

#define INC_EAX_MEM (   n)    { EMIT3(0x40FF,n); INSTR("inc [eax%p]",n); }

Definition at line 168 of file i386.c.

#define DEC_EAX_MEM (   n)    { EMIT3(0x48FF,n); INSTR("dec [eax%p]",n); }

Definition at line 169 of file i386.c.

#define RET   { EMIT1(0xC3); INSTR("ret"); }

Definition at line 171 of file i386.c.

#define ADD_EAX_CONST_4 (   n)    { EMIT5(0x05,n); INSTR("add eax,%d",n); }

Definition at line 173 of file i386.c.

#define ADD_ESI_CONST_4 (   n)    { EMIT6(0xC681,n); INSTR("add esi,%d",n); }

Definition at line 174 of file i386.c.

#define CMP_EBX_CONST (   n)    { EMIT3(0xFB83,n); INSTR("cmp ebx,%d",n); }

Definition at line 176 of file i386.c.

#define CMP_EAX_CONST (   n)    { EMIT5(0x3D,n); INSTR("cmp eax,%d",n); }

Definition at line 177 of file i386.c.

#define CMP_EAX_ATOM (   a)    { EMIT5(0x3D,a); INSTR("cmp eax,%l",a); }

Definition at line 178 of file i386.c.

#define CMP_ID_ERROR
Value:
INSTR("cmp [eax+ID],ERROR_ID"); }

Definition at line 179 of file i386.c.

#define CMP_MEM_EBP (   ofs,
  val 
)
Value:
{ EMIT2(0x7D80); EMIT1(ofs); EMIT1(val);\
INSTR("cmp [eax%p],%d",ofs,val); }

Definition at line 181 of file i386.c.

#define CMP_MEM_OFS_CONST_4 (   ofs,
 
)    { EMIT6(0x3D81,ofs); EMIT4(n); INSTR("cmp [%d],%a", ofs, n); }

Definition at line 183 of file i386.c.

#define CMP_MEM_OFS_CONST_1 (   ofs,
 
)
Value:
{ EMIT6(0x3D80,ofs); EMIT1(n); \
INSTR("cmp [%d],%d", ofs, n); }

Definition at line 184 of file i386.c.

#define JE_EXIT   { EMIT6(0x840F,REL(EXIT)); INSTR("je exit"); }

Definition at line 188 of file i386.c.

#define JE (   addr,
  name 
)    { EMIT6(0x840F,REL(addr)); INSTR("je %s",name); }

Definition at line 189 of file i386.c.

#define JNE (   addr,
  name 
)    { EMIT6(0x850F,REL(addr)); INSTR("jne %s",name); }

Definition at line 190 of file i386.c.

#define JNZ (   addr,
  name 
)    { EMIT6(0x850F,REL(addr)); INSTR("jnz %s",name); }

Definition at line 191 of file i386.c.

#define JMP_EXIT   { EMIT5(0xE9,REL(EXIT)); INSTR("jmp exit"); }

Definition at line 193 of file i386.c.

#define JMP (   addr,
  name 
)    { EMIT5(0xE9,REL(addr)); INSTR("jmp %s",name); }

Definition at line 194 of file i386.c.

#define JMP_ATOM (   addr,
  name 
)    { EMIT5(0xE9,REL(addr)); INSTR("jmp %a",name); }

Definition at line 195 of file i386.c.

#define JMP_EAX (   name)    { EMIT2(0xE0FF); INSTR("jmp %a",name); }

Definition at line 196 of file i386.c.

#define CALL (   addr,
  name 
)    { EMIT5(0xE8,REL(addr)); INSTR("call %s",name); }

Definition at line 198 of file i386.c.

#define CALL_ATOM (   addr,
  name 
)    { EMIT5(0xE8,REL(addr)); INSTR("call %a",name); }

Definition at line 199 of file i386.c.

#define CALL_MEM (   addr,
  name 
)    { EMIT6(0x15FF,addr); INSTR("call [%a]",name); }

Definition at line 201 of file i386.c.

#define CALL_MEM_EAX (   addr,
  name 
)    { EMIT6(0x90FF,addr); INSTR("call [eax+%s]",name); }

Definition at line 202 of file i386.c.

#define FSTPF_MEM_ESP   { EMIT2(0x1CD9); EMIT1(0x24); INSTR("fstpf [esp]"); }

Definition at line 204 of file i386.c.

#define FSTPD_MEM_ESP   { EMIT2(0x1CDD); EMIT1(0x24); INSTR("fstpd [esp]"); }

Definition at line 205 of file i386.c.

#define INT_3   { EMIT1(0xCC); INSTR("int 3"); }

Definition at line 207 of file i386.c.

#define NOP   { EMIT1(0x90); INSTR("nop"); }

Definition at line 208 of file i386.c.

Function Documentation

uint_t relative ( context_t ctx,
int  addr 
)
Parameters
ctxcompilation context
addrtarget address
Returns
calculated offset

Calculates a relative offset, which is commonly used in JPM and CALL instructions. The parameter ADDR is absolute target address. The result is the same target, but relative to the current IP position.

Definition at line 92 of file i386.c.

93 {
94  if( ctx->generate )
95  {
96  int next_instruction = IP + 4;
97  return (uint_t)(addr-next_instruction);
98  }
99  else
100  return 0;
101 }
void asm_label ( context_t ctx,
chars_t  label 
)
Parameters
ctxcontext
labellabel

Dumps disassembler's label followed by semicolon

Definition at line 111 of file i386.c.

112 {
113  #ifdef ADVANCED
114  disasm( ctx, 4, label );
115 #endif //ADVANCED
116 }
void asm_prologue ( context_t ctx,
atom_t  func,
int  check 
)
Parameters
ctxcompilation context
funcfunction which prologue to generate
checkadd code for checking inputs

Generates the prologue of a function. This is an initializating sequences of machine instructions needed to setup stack, system data and local vars.

Generated code:

;; initialize stack push ebp ; caller's frame [EBP+0] mov ebp,esp ; EBP=current frame push esi ; parent's frame [EBP-4] push func ; parent atom [EBP-8]

;; initialize system data push repeat_chain ; for root; unbound for non-root call use push 2 ; result of IFTRUE [EBP-16] mov eax,unbound ; default result of the function

;; initialize local variables push empty_list ; runtime locals [EBP-20] push eax ; once for each local variable

;; check all input params ; if check!=0 push ebp call rt_check_inputs CMP_ID_ERROR JE_EXIT;

Definition at line 248 of file i386.c.

249 {
250  atom_t a;
251 
252  INFO( "" );
253  INFO( "=========================" );
254  INFO( " FUNCTION %a", NAME(func) );
255  INFO( "=========================" );
256  INFO( "" );
257 
258  LABEL( "%a:", NAME(func) );
259 
260  PUSH_EBP; REM( "function prologue" );
261  MOV_EBP_ESP;
262  PUSH_ESI;
263  PUSH_ATOM( func ); REM( "parent atom" );
264 
265  INFO( "" );
266  INFO( "initialize system data" );
267  if( func==root )
268  {
269  MOV_MEM_OFS_EBP( &root_frame ); REM( "store root frame" );
270  PUSH_ATOMSTR( repeat_chain, TEXT("repeat_chain") );
271  CALL( use, TEXT("use") );
272  }
273  else
274  {
275  PUSH_ATOM( unbound );
276  }
277 
278  PUSH_CONST(2); REM( "IFTRUE status" );
279  MOV_EAX_ATOM(unbound); REM( "default result of %a", NAME(func) );
280 
281  INFO( "" );
282  INFO( "initialize local variables" );
283  PUSH_ATOM( empty_list ); REM( "runtime locals [EBP-16]" );
284 
285  int ofs = BASE_OFFSET_LOCALS-4;
286  for( a=LOCALS(func); IS_NOT_EMPTY(a); a=CDR(a) )
287  if( IS_VARIABLE(CAR(a))&& IS_NORMAL(CAR(a)) )
288  {
289  // print the name and the address of the local var
290  PUSH_EAX; REM( "local %a [EBP%p]", NAME(CAR(a)), ofs );
291  ofs-=4;
292  }
293 
294  // if we are not making the topmost prologue
295  // and if we are not making the prologue of RUN
296  // then add code to check all inputs
297  if( check && func!=root && NAME(func)!=word_to )
298  {
299 //printf("func anme="); dumpln(NAME(func)); //@@
300  INFO( "check all inputs" );
301  PUSH_EBP; REM( "give local frame to checker" );
302  CALL( rt_check_inputs, TEXT("rt_check_inputs") );
304  JE_EXIT;
305  }
306 }
void asm_preepilogue ( context_t ctx)

Definition at line 342 of file i386.c.

343 {
344  MOV_EBX_CONST(0);
345 }
void asm_epilogue ( context_t ctx,
atom_t  func,
int  is_macro 
)
Parameters
ctxcompilation context
funcfunction which epilogue to generate
is_macroif set then local variables must be copies

Generates the epilogue of a function. This is a finalizating sequences of machine instructions needed to recover stack and local variables.

Generated code:

mov     ebx,0

exit:

push ebp ; push current frame only if is_macro is set call copy_local_vars ; only if is_macro is set

;; free local variables call deuse ; once for each local call deuse ; for runtime locals

;; free system data pop edx ; free result of IFTRUE call deuse ; free repeat chain

;; recover frame pointers pop edx ; free parent atom pop esi mov esp,ebp pop ebp ret

Definition at line 346 of file i386.c.

347 {
348  atom_t a;
349 
350  INFO( "" );
351 LABEL( "exit:" );
352 
353  if( is_macro==COMPILE_AS_MACRO )
354  {
355  //INT_3; NOP; NOP; NOP;
356  PUSH_EAX;
357  PUSH_EBX;
358  PUSH_EBP; REM("push current frame");
359  CALL( copy_local_vars, TEXT("copy_local_vars") );
360  POP_EDX;
361  POP_EBX;
362  POP_EAX;
363  //NOP; NOP; NOP;
364  }
365 
366  INFO( "free local variables" );
367  for( a=LOCALS(func); IS_NOT_EMPTY(a); a=CDR(a) )
368  if( IS_VARIABLE(CAR(a)) && IS_NORMAL(CAR(a)) )
369  CALL( deuse, TEXT("deuse") );
370  CALL( deuse, TEXT("deuse") ); REM("also free dynamic variables");
371 
372  INFO( "" );
373  INFO( "free system data" );
374  POP_EDX; REM( "free result of IFTRUE" );
375  CALL( deuse, TEXT("deuse") ); REM( "free repeat chain" );
376 
377  INFO( "" );
378  INFO( "recover frame pointers" );
379  POP_EDX; REM( "delete link to parent" );
380  POP_ESI;
381  MOV_ESP_EBP;
382  POP_EBP;
383  RET; REM( "end of %a", NAME(func) );
384 }
void asm_push_atom ( context_t ctx,
atom_t  atom 
)
Parameters
ctxcompilation context
atomatom to push

Generates machine code which pushes atom in the stack and increases its reference count. The atom reference count is NOT increased if it is UNBOUND or EMPTY LIST.

Note
Assumes the reference count is at the beginning of the atom - i.e. at offset 0.

Generated code:

push {atom} call {use} ; if not UNBOUND or EMPTY LIST

Definition at line 408 of file i386.c.

409 {
410  PUSH_ATOM( atom );
411  if( !IS_UNBOUND(atom) && !IS_EMPTY(atom) )
412  {
413  CALL( use, TEXT("use") );
414  }
415 }
void asm_pop_atom ( context_t ctx)
Parameters
ctxcompilation context

Generates machine code which pops atom from the stack and deuses it.

Generated code: call {deuse}

Definition at line 428 of file i386.c.

429 {
430  CALL( deuse, TEXT("deuse") );
431 }
void asm_pop_dummy ( context_t ctx)
Parameters
ctxcompilation context

Generates machine code which pops data from the the stack and then ignores it.

Generated code: pop edx

Definition at line 444 of file i386.c.

445 {
446  POP_EDX;
447 }
void asm_push_result ( context_t ctx)
Parameters
ctxcompilation context

Generates machine code which push the value returned by a function into the stack.

Generated code: push eax

Definition at line 460 of file i386.c.

461 {
462  PUSH_EAX; REM( "move result in stack " );
463 }
void asm_result_proc ( context_t ctx,
atom_t  source 
)
Parameters
ctxcompilation context
sourcesource of the function

Generates code which check whether the result of a command is acceptible. The source parameter points to the source where the procedure is called. It is used to locate the error position in case of errors.

Definition at line 477 of file i386.c.

478 {
479  INFO( "" );
480  INFO( "check for errors in proc %a", CAR(source) );
481  PUSH_SOURCE( source );
482  CALL( rt_cmdchk, TEXT("rt_cmdchk") ); REM( "check result, exit if error" );
483  CMP_ID_ERROR;
484  JE_EXIT;
485  MOV_EBX_CONST( 0 );
486 }
void asm_result_unknown ( context_t ctx,
atom_t  source 
)
Parameters
ctxcompilation context
sourcesource of the function

Generates code which check whether the result of an expression is acceptible. Actually, any result is acceptible.

Definition at line 498 of file i386.c.

499 {
500  INFO( "" );
501  INFO( "check for errors in %a", CAR(source) );
502  PUSH_SOURCE( source );
503  CALL( rt_exprchk, TEXT("rt_exprchk") ); REM( "check result" );
504 }
void asm_result_func ( context_t ctx,
atom_t  source 
)
Parameters
ctxcompilation context
sourcesource of the function

Generates code which check whether the result of a function is acceptible. The source parameter points to the source where the function is called. It is used to locate the error position in case of errors.

Definition at line 518 of file i386.c.

519 {
520  INFO( "" );
521  INFO( "check for errors in func %a", CAR(source) );
522  PUSH_SOURCE( source ); REM( "source" );
523  CALL( rt_funchk, TEXT("rt_funchk") ); REM( "check result" );
524  asm_push_result( ctx );
525 }
int asm_static_link ( context_t ctx,
atom_t  var 
)
Parameters
ctxcompilation context
varvar to which link is sought
Returns
offset of the variable

Generates code with store the stack frame address of a variable in ESI regiser. The result of the function is the offset of the variable (if it is normal variable) or its address (if it is function or command).

Generated code:

mov esi,ebp mov esi,ss:[esi-4] ; repeated depth times

Definition at line 545 of file i386.c.

546 {
547  int depth = LEVEL(ctx->parent)-LEVEL(var)+1;
548 
549  #ifdef SAFEMODE
550  assert(depth>=0);
551  #endif
552 
553  MOV_ESI_EBP; REM( "ESI=stack frame of %a", NAME(var) );
554  for( ; depth; depth-- ) MOV_ESI_SSMEM_ESI_4;
555 
556  return OFFSET( var );
557 }
void compile_system_reference ( context_t ctx,
atom_t  name 
)
Parameters
ctxcompilation context
namevariable's name

Compiles a reference to a system variable. It is assumed that the variable exists.

Definition at line 568 of file i386.c.

569 {
570  atom_t var = find_var( name, ctx->parent );
571 
572  #ifdef SAFEMODE
573  assert( var );
574  assert( IS_VARIABLE( var ) );
575  #endif //SAFEMODE
576 
577  asm_reference( ctx, var, unbound, 0 );
578  CALL( use, TEXT("use") );
579 }
void asm_reference ( context_t ctx,
atom_t  var,
atom_t  source,
int  check 
)
Parameters
ctxcompilation context
varvariable which value is referenced
sourcesource of var reference
checkif 0 then do not check result

Generates code for referencing variable's value. The generated code depends on depth - this is the difference between depths of syntax levels of the current context and the context where the var's value exist.

If the variable is primitive then it is stored in globals and is accessed directly – i.e. it's value is not stored in the stack.

If check==0 push the value to the stack and exit. Otherwise generate code to check whether the value is not UNBOUND (i.e. to check whether the variable has been assigned a value)

(a) var is primitive push [{address}]

(b) user-defined var {static link} push [esi+offset] ; push value

if check!=0 then also generate:

push {source} call asm_use_var ; use new value cmp [eax+OFFSET_ID],ERROR_ID je exit push eax

Definition at line 619 of file i386.c.

620 {
621  if( IS_PRIMITIVE(var) )
622  { // case (a) - primitive variable
623  int addr = (int)&VALUE(var);
624  PUSH_MEM( addr );
625  }
626  else
627  { // case (b) - user-defined variable
628  int offset = asm_static_link( ctx, var );
629  PUSH_MEM_ESI( offset );
630  }
631  REM( "value of %a", NAME(var) );
632 
633  // generate code to check whether
634  // the variable has a value
635  if( check )
636  {
637  PUSH_SOURCE( source ); REM( "source" );
638  CALL( rt_use_var, TEXT("rt_use_var") );
639  //CMP_ID_ERROR;
640  //JE_EXIT;
641  PUSH_EAX; REM( "still value of %a", NAME(var) );
642  }
643 }
void asm_make_direct ( context_t ctx,
atom_t  var,
atom_t  source 
)

For all user-defined variables the value of depth determines what code is generated. This variable is the difference between the context where the var is defined and the context where the var is used. The value of delpth is used to generate code to reach the proper context.

Code generation patterns (assumes the new value is already pushed onto the stack):

(a) primitive (system) variables push [{address}] ; push old value call deuse ; deuse and pop old value mov eax,[esp] ; get new value mov [{address}],eax ; store new value

(b) user-defined var {static} ; calculate base pointer in ESI push [esi+offset] ; push old value call deuse ; deuse and pop old value mov eax,[esp] ; get new value mov [esi+offset],eax ; store new value

Definition at line 684 of file i386.c.

685 {
686  if( IS_PRIMITIVE(var) || IS_GLOBAL(var) )
687  { // case (a)
688  int addr = (int)&VALUE(var);
689 
690  // NB! No need to override default segment,
691  // because it is already SS
692  PUSH_MEM( addr ); REM( "free old value of %a", NAME(var) );
693  CALL( deuse, TEXT("deuse") );
694  MOV_EAX_MEM_ESP; REM( "set new value of %a", NAME(var) );
695  MOV_MEM_OFS_EAX( addr );
696  }
697  else
698  {
699  INFO( "" );
700  INFO( "assign new value to %a", NAME(var) );
701  int offset = asm_static_link( ctx, var );
702  PUSH_MEM_ESI( offset ); REM( "free old value of %a", NAME(var) );
703  CALL( deuse, TEXT("deuse") );
704  MOV_EAX_MEM_ESP; REM( "set new value of %a", NAME(var) );
705  MOV_MEM_ESI_EAX( offset );
706  }
707 
708  // Generates code which check whether the result
709  // of a make is acceptible. The \c source parameter
710  // points to the source where the procedure is called.
711  // It is used to locate the error position in case
712  // of errors.
713 
714  INFO( "" );
715  INFO( "check for errors of %a", CAR(source) );
716  PUSH_SOURCE( source );
717  CALL( rt_makechk, TEXT("rt_makechk") ); REM( "check result atom" );
718  CMP_ID_ERROR; REM( "is error atom?" );
719  JE_EXIT;
720 }
void asm_push_value_addr ( context_t ctx,
atom_t  var 
)
Parameters
ctxcompilation context
varvariable which value is looked for

Generates code that calculates and pushes in the the stack the address of the value of a variable known at compile time.

(a) primitive (system) variables push {address} ; push value's address

(b) user-defined var {static} ; calculate base pointer in ESI add esi,offset ; adjust for offset push esi ; push value's address

Definition at line 741 of file i386.c.

742 {
743  if( IS_PRIMITIVE(var) )
744  { // case (a)
745  int addr = (int)&VALUE(var);
746 
747  PUSH_CONST( addr ); REM( "address of %a's value", NAME(var) );
748  }
749  else
750  {
751  int offset = asm_static_link( ctx, var );
752  ADD_ESI_CONST_4( offset ); REM( "address of %a's value", NAME(var) );
753  PUSH_ESI;
754  }
755 }
void asm_call_atom ( context_t ctx,
atom_t  var,
int  params 
)
Parameters
ctxcompilation context
varatom to call
paramsnumber of actual inputs

Generates machine code which calls a logo function. The input atom contains the name of the function.

Generated code (for functions with fixed number of inputs):

  • call {function}

Generated code (for functions with variable number of inputs or not-primitive):

  • push {param count}
  • call {function}
  • pop edx

Definition at line 775 of file i386.c.

776 {
778 
779  // all variadic functions need one more parameter
780  if( variadic || !GET_FLAGS(var,FLAG_PRIMITIVE) )
781  {
782  PUSH_CONST( params ); REM( "param count of %a", NAME(var) );
783  }
784 
785 
786  // test for special system-defined variables-inputs
787  // first test for print-related system inputs
788  if( GET_FLAGS(var,FLAG_PRINT_VARS) )
789  {
793  }
794  if( GET_FLAGS(var,FLAG_EQUAL_VARS) )
795  {
797  }
798 
799  // test for run-time access to parent
800  if( GET_FLAGS(var,FLAG_PUSH_PARENT) )
801  {
802  PUSH_CONST( (int)ctx->parent ); REM( "push parent of %a", NAME(var) );
803  PUSH_EBP; REM( "push current frame" );
804  }
805 
806  if( IS_PRIMITIVE(var) )
807  {
808  if( !ADDRESS(var) )
809  {
810  printf("This primitive is not defined yet -> ");
811  dumpln(NAME(var));
812  return;
813  }
814  CALL_ATOM( (void*)ADDRESS(var), NAME(var) );
815  }
816  else
817  {
818  // prepare static link
819  asm_static_link( ctx, var );
820  CALL_MEM( &ADDRESS(var), NAME(var) );
821  }
822 
823  // postprocessing of run-time access to parent
824  if( GET_FLAGS(var,FLAG_PUSH_PARENT) )
825  {
826  POP_EDX; REM("remove static link");
827  POP_EDX; REM("remove parent");
828  }
829 
830  // postprocessing of system inputs
831  if( GET_FLAGS(var,FLAG_EQUAL_VARS) )
832  {
833  asm_pop_atom( ctx ); REM( "remove %a", NAME(caseignoredp) );
834  }
835  if( GET_FLAGS(var,FLAG_PRINT_VARS) )
836  {
837  asm_pop_atom( ctx ); REM( "remove %a", NAME(printdepthlimit) );
838  asm_pop_atom( ctx ); REM( "remove %a", NAME(printwidthlimit) );
839  asm_pop_atom( ctx ); REM( "remove %a", NAME(fullprintp) );
840  }
841 
842  // postprocessing of all variadic functions
843  if( variadic || !GET_FLAGS(var,FLAG_PRIMITIVE) )
844  {
845  POP_EDX; REM("remove param count");
846  }
847 }
void asm_runtime_reference ( context_t ctx)
Parameters
ctxcompilation context

Generates machine code which finds the value of a variable and pushes it in the stack. The name is in the stack, i.e. it is not processed at compile time.

push {parent} push ebp call : pop edx pop edx

Definition at line 866 of file i386.c.

867 {
868  // always push the parent
869  PUSH_CONST( (int)ctx->parent ); REM( "push parent" );
870  PUSH_EBP; REM( "push static link" );
871  CALL( rt_reference, TEXT(":") );
872  POP_EDX; REM( "remove static link" );
873  POP_EDX; REM( "remove parent" );
874 }
void asm_dump_source ( context_t ctx,
atom_t  source 
)
Parameters
ctxcompilation context
sourcesource to dump

Generates code which dumps the current source. This code is generally placed before calling user-defined function of command.

Definition at line 886 of file i386.c.

887 {
888  INFO( "" );
889  PUSH_SOURCE( source ); REM( "dump source" );
890  CALL( rt_predump, TEXT("rt_predump") );
891  INFO( "" );
892 }
void asm_empty_body ( context_t ctx)
Parameters
ctxcompilation context

Generates the body of an empty function. This body just sets the result to be unbound atom.

Generated code:

  • push (unbound)
  • call use
  • pop eax

Definition at line 907 of file i386.c.

908 {
909  INFO( "" );
910  MOV_EAX_ATOM( unbound ); REM( "there is no result" );
911 }
void asm_output ( context_t ctx,
atom_t  source,
int  true_output 
)
Parameters
ctxcompilation context
sourcesource of the OUTPUT command
true_outputflag whether OUPUT is real or simulated

Generates code for output statement. Before the execution of asm_output() the stack contains the new value to output.

Generated code:

mov     ebx,true_output

pop eax ; load value in EAX jmp exit

Definition at line 930 of file i386.c.

931 {
932  INFO( "" );
933  INFO( "output current result" );
934 
935  #ifdef ADVANCED
936  if( OPTION_RUNTIME )
937  {
938  PUSH_SOURCE( source ); REM( "dump source" );
939  CALL( rt_dump, TEXT("dump") );
940  }
941  #endif
942 
943  MOV_EBX_CONST( true_output );
944  POP_EAX; REM( "get current result in EAX" );
945  JMP_EXIT;
946 }
void asm_stop ( context_t ctx,
atom_t  source 
)
Parameters
ctxcompilation context
sourcesource of the STOP command

Generates code for stop statement.

Generated code:

mov ebx,1 mov eax,{stopped} ; load value in EAX jmp exit

Definition at line 962 of file i386.c.

963 {
964  INFO( "exit with no result" );
965 
966  #ifdef ADVANCED
967  if( OPTION_RUNTIME )
968  {
969  PUSH_SOURCE( source ); REM( "dump source" );
970  CALL( rt_dump, TEXT("rt_dump") );
971  }
972  #endif
973 
974  MOV_EBX_CONST( 1 );
975  MOV_EAX_ATOM( stopped ); REM( "stopped" );
976  JMP_EXIT;
977 }
void asm_boolean ( context_t ctx,
atom_t  source 
)
Parameters
ctxcompilation context
sourcesource of the expression

Generates code that checks the top value in the stack is TRUE or FALSE. In case of TRUE sets EAX = false_true[1]. In case of FALSE sets EAX = false_true[0]. If the value is neither TRUE nor FALSE sets EAX to an error atom

Generated code:

call    rt_boolchk

cmp [eax+OFFSET_ID],ERROR_ID je exit

Definition at line 999 of file i386.c.

1000 {
1001  INFO( "" );
1002  INFO( "check boolean result" );
1003  PUSH_SOURCE( source ); REM( "source" );
1004  CALL( rt_boolchk, TEXT("rt_boolchk") ); REM( "exit if not boolean" );
1005  CMP_ID_ERROR;
1006  JE_EXIT;
1007 }
int asm_if_prologue ( context_t ctx)
Parameters
ctxcompilation context
Returns
branch address

Generates prologue code for the if command. Prologue is the code which stands right before the code for then. It is used to direct execution towards the then or the else parts.

It is assumed that the code for the condition is already ready and EAX contains the address of either false_true[0] or false_true[1].

The return value is set to the address of the else component of the je instruction. It is used to set the correct offset once the size of then-commands is known.

Generated code: cmp eax,FALSE je else

Definition at line 1034 of file i386.c.

1035 {
1036  CMP_EAX_ATOM( false_true[0] ); REM( "is it false?" );
1037  JE( 0, TEXT("$else") ); REM( "goto if-else block" );
1038  return LOCAL_IP-4;
1039 }
int asm_if_epilogue ( context_t ctx)
Parameters
ctxcompilation context
Returns
branch address

Generates epilogue code for the if command. Epilogue is the code which stands right after the code for the then-instructions. It contains only a jump over the else-instructions directly to the end of the if command.

Generated code: jmp ifend

Definition at line 1056 of file i386.c.

1057 {
1058  JMP( 0, TEXT("ifend") ); REM( "skip if-else block" );
1059  return LOCAL_IP-4;
1060 }
void asm_fix ( context_t ctx,
int  addr 
)
Parameters
ctxcompilation context
addraddress of data to fix
Returns
branch address

Fixes a relative offset from a given position to the current position as defined by ctx. This is used when there is a forward conditional or inconditional jump, which target is unknown at compile time.

The parameter addr is a 0-based address (i.e. it is an offset relative to START_IP).

Definition at line 1078 of file i386.c.

1079 {
1080  reemit_4( ctx, addr, ctx->size-addr-4 );
1081 }
int asm_repeat_prologue_const ( context_t ctx,
int  cnt 
)
Parameters
ctxcompilation context
cntnumber of repetitions
Returns
branch address

Generates const-prologue code for the repeat command. Const-prologue is used when the number of repetitions is known at compile time (currently this means it is a constant).

The prologue initializes the repeat by calling rt_repeat_enter to set up a new element of the repeat chain.

The return value of the function is the address of the instruction right after the prologue. This address is used by asm_repeat_epilogue() and is absolute address.

Generated code:

push {count} push ebp call rt_repeat_enter

Definition at line 1110 of file i386.c.

1111 {
1112  PUSH_CONST( cnt ); REM( "repeat count" );
1113  PUSH_EBP; REM( "static link" );
1114  CALL( rt_repeat_enter, TEXT("rt_repeat_enter") ); REM( "initialize repeat" );
1115 
1116  INFO( "" );
1117  asm_label( ctx, TEXT("$rep:") );
1118  INFO( "start bofy of repeat" );
1119 
1120  return IP;
1121 }
int asm_repeat_prologue_expr ( context_t ctx,
atom_t  source,
int *  branch2 
)
Parameters
ctxcompilation context
sourcesource of the expression
branch2address of branch to skip over the whole repeat
Returns
branch address

Generates expr-prologue code for the repeat command. Expr-prologue is used when the number of repetitions is an expression, i.e. it is not known at compile time.

The prologue generates code to calculate the actual number of repetitions. It checks whether there was an error during calculation. If not, it checks whether the number of repetitions is valid. Finally the prologue initializes the repeat by calling rt_repeat_enter to set up a new element of the repeat chain.

The return value of the function is the address of the instruction right after the prologue. This address is used by asm_repeat_epilogue() and is absolute address.

Generated code:

{expr} push {source} call rt_repchk cmp [eax+OFFSET_ID],ERROR_ID je exit

push eax mov [eax+REPLIMIT],eax call deuse

cmp eax,0 je skip_repeat ][ ; <-branch2

push eax push ebp call rt_repeat_enter $rep:

Definition at line 1169 of file i386.c.

1170 {
1171  INFO( "" );
1172  INFO( "check validity of repeat count" );
1173  PUSH_SOURCE( source ); REM( "source" );
1174  CALL( rt_repchk, TEXT("rt_repchk") ); REM( "exit if invalid" );
1175  CMP_ID_ERROR;
1176  JE_EXIT;
1177 
1178  PUSH_EAX; REM( "free repeat count expression" );
1179  MOV_EAX_MEM_EAX( OFFSET_INT ); REM( "get repeat count" );
1180  CALL( deuse, TEXT("deuse") );
1181 
1182  CMP_EAX_CONST( 0 ); REM( "exit if it is 0" );
1183  JE( 0, TEXT("skip_repeat") );
1184  *branch2 = LOCAL_IP-4;
1185 
1186  PUSH_EAX; REM( "repeat count" );
1187  PUSH_EBP; REM( "static link" );
1188  CALL( rt_repeat_enter, TEXT("rt_repeat_enter") ); REM( "initialize repeat" );
1189 
1190  asm_label( ctx, TEXT("$rep:") );
1191 
1192  return IP;
1193 }
void asm_repeat_epilogue ( context_t ctx,
int  branch,
int  branch2 
)
Parameters
ctxcompilation context
branchbranch for repeat's loop
branch2branch for skipping repeat

Generates epilogue code for the repeat command. There are two prologues for repeat, but the epilogue is the same for both of them.

The epilogue of repeat decrements the repeat count and if it is not zero, then loops back to the branch address, which is provided as parameter.

If the value of branch2 is -1, then the repeat with constant number of repetitions and branch2 is ignored. Otherwise it contains the address where a branch is made over the whole body of the repeat when the repetition number is 0.

Generated code: (note: {body} is not a part of the epilogue)

$rep: {body} mov eax,[ebp+REPEATCHAIN] mov eax,[eax+CAR_OFFSET] inc [eax+REPCOUNT] dec [eax+REPLIMIT] jnz $rep

$skip: push ebp call rt_repeat_exit

Definition at line 1239 of file i386.c.

1240 {
1241 
1242  INFO( "" );
1243  INFO( "calculate next loop of repeat" );
1244  MOV_EAX_MEM_EBP( BASE_OFFSET_REPEATCHAIN ); REM( "get repeat chain" );
1245  MOV_EAX_MEM_EAX( CAR_OFFSET ); REM( "get current repeat node" );
1246  INC_EAX_MEM( OFFSET_REPCOUNT ); REM( "increase done repeats" );
1247  DEC_EAX_MEM( OFFSET_REPLIMIT ); REM( "decrease left repeats" );
1248 
1249  //PUSH_MEM_EBP(BASE_OFFSET_REPEATCHAIN);
1250  //PUSH_MEM_EAX(OFFSET_REPCOUNT);
1251  //PUSH_MEM_EAX(OFFSET_REPLIMIT);
1252  //CALL( rt_repeat_debug, TEXT("") );
1253 
1254  JNZ( branch, TEXT("$rep") );
1255 
1256  if( branch2!=-1 )
1257  {
1258  INFO( "" );
1259  asm_label( ctx, TEXT("skip_repeat:") );
1260  INFO( "no more loops" );
1261  asm_fix( ctx, branch2 );
1262  }
1263 
1264  PUSH_EBP; REM( "static link" );
1265  CALL( rt_repeat_exit, TEXT("rt_repeat_exit") );
1266 }
int asm_forever_prologue ( context_t ctx)
Parameters
ctxcompilation context
Returns
branch address

Generates prologue code for the forever command.

The prologue initializes the forever by calling rt_forever_enter to set up a new element of the repeat chain.

The return value of the function is the address of the instruction right after the prologue. This address is used by asm_forever_epilogue().

Generated code:

push ebp call rt_forever_enter forever:

Definition at line 1290 of file i386.c.

1291 {
1292  PUSH_EBP; REM("static link");
1293  CALL( rt_forever_enter, TEXT("rt_forever_enter") ); REM( "initialize forever" );
1294 
1295  INFO( "" );
1296  asm_label( ctx, TEXT("forever:") );
1297  INFO( "start bofy of forever" );
1298 
1299  return IP;
1300 }
void asm_forever_epilogue ( context_t ctx,
int  branch 
)
Parameters
ctxcompilation context
branchbranch for forever's loop

Generates epilogue code for the forever command.

Generated code: (note: {body} is not a part of the epilogue)

forever:: {body} mov eax,[ebp+REPEATCHAIN] mov eax,[eax+CAR_OFFSET] inc [eax+REPCOUNT] jmp forever

Definition at line 1320 of file i386.c.

1321 {
1322  INFO( "" );
1323  INFO( "calculate next loop of forever" );
1324  MOV_EAX_MEM_EBP( BASE_OFFSET_REPEATCHAIN ); REM( "get current repeat node" );
1325  MOV_EAX_MEM_EAX( CAR_OFFSET ); REM( "get current repeat node" );
1326  INC_EAX_MEM( OFFSET_REPCOUNT ); REM( "increase done repeats" );
1327  JMP( branch, TEXT("forever") );
1328 }
void asm_push_frame ( context_t ctx)
Parameters
ctxcompilation context

Generates code for pushing the frame pointer which is stored in EBP.

Generated code:

push ebp

Definition at line 1342 of file i386.c.

1343 {
1344  PUSH_EBP; REM("push current frame");
1345 }
void asm_pop_frame ( context_t ctx)
Parameters
ctxcompilation context

Generates code for popping the frame pointer previously pushed by asm_push_frame(). The actual value that is popped out is not used for anything.

Generated code:

pop edx

Definition at line 1361 of file i386.c.

1362 {
1363  POP_EDX; REM( "remove pushed frame" );
1364 }
void asm_push_mode ( context_t ctx,
int  mode 
)
Parameters
ctxcompilation context
modemode to push

Generates code for pushing the mode of a function call. The mode indicates whether the function is called as a function or as a command. The values of mode should be either COMPILE_AS_FUNC or COMPILE_AS_PROC.

Generated code:

push {mode}

Definition at line 1382 of file i386.c.

1383 {
1384  PUSH_CONST( mode );
1385  if( mode==COMPILE_AS_FUNC )
1386  REM( "call as function" );
1387  else
1388  REM( "call as procedure" );
1389 }
void asm_adjust_result ( context_t ctx)
Parameters
ctxcompilation context

Generates code which adjust the result of a command. This is needed when EAX register is left unchanged from the last expression.

Generated code:

mov eax,{unbound} ; load value in EAX

Definition at line 1404 of file i386.c.

1405 {
1406  MOV_EAX_ATOM( unbound ); REM( "set void result" );
1407 }
void asm_pop_result ( context_t ctx)
Parameters
ctxcompilation context

Generates code which adjust the result of a function. This is needed when the result is in the stack, but it is needed to be in EAX.

Generated code:

pop eax

Definition at line 1422 of file i386.c.

1423 {
1424  POP_EAX; REM( "get current result" );
1425 }
int asm_while_prologue ( context_t ctx,
int  is_while,
int  is_do 
)
Parameters
ctxcompilation context
is_whilewhile=1, until=0
is_dodo.while&do.until=1, while&until=0
Returns
branch address

Generates prologue code for the while or the until command (depending on the value of is_while parameter). Actually no code is generated, as long as the the prologue is just a label.

Generated code (is_while==1 & is_do==0):

while:

Generated code (is_while==0 & is_do==0):

until:

Generated code (is_while==1 & is_do==1):

do.while:

Generated code (is_while==0 & is_do==1):

do.until:

Definition at line 1459 of file i386.c.

1460 {
1461  if( is_do )
1462  {
1463  if( is_while )
1464  asm_label( ctx, TEXT("do.while:") );
1465  else
1466  asm_label( ctx, TEXT("do.until:") );
1467  }
1468  else
1469  {
1470  if( is_while )
1471  asm_label( ctx, TEXT("while:") );
1472  else
1473  asm_label( ctx, TEXT("until:") );
1474  }
1475  return IP;
1476 }
int asm_while_inlogue ( context_t ctx,
atom_t  source,
int  is_while 
)

push eax mov eax,[eax+INT] call deuse cmp eax,0 (for while) or 1 (for until) je skip_while

Definition at line 1511 of file i386.c.

1512 {
1513  INFO( "" );
1514  INFO( "test condition of while/until" );
1515  PUSH_SOURCE( source ); REM( "source" );
1516  CALL( rt_whlchk, TEXT("rt_whlchk") ); REM( "check condition" );
1517  CMP_ID_ERROR; REM( "exit if error" );
1518  JE_EXIT;
1519 
1520  PUSH_EAX; REM( "free condition atom" );
1521  MOV_EAX_MEM_EAX( OFFSET_INT ); REM( "get condition result" );
1522  CALL( deuse, TEXT("deuse") );
1523 
1524  CMP_EAX_CONST( 1-is_while ); REM( "exit if condition fails" );
1525  JE( 0, is_while?TEXT("skip_while"):TEXT("skip_until") );
1526 
1527  return LOCAL_IP-4;
1528 }
void asm_while_epilogue ( context_t ctx,
int  loop_branch,
int  skip_branch,
int  is_while 
)
Parameters
ctxcompilation context
loop_branchbranch for while/until's loop
skip_branchbranch to skip while/until
is_whilewhile=1, until=0

Generates epilogue code for the while or until command.

Generated code: (note: {body} is not a part of the epilogue)

$whl: ... {body} jmp $whl skip_while: mov eax,(unbound)

Definition at line 1552 of file i386.c.

1553 {
1554  INFO( "" );
1555  INFO( "finalization of while/until" );
1556  JMP( loop_branch, is_while?TEXT("while"):TEXT("until") );
1557 
1558  asm_label( ctx, is_while?TEXT("skip_while"):TEXT("$skip_until") );
1559  asm_fix( ctx, skip_branch );
1560 
1561  MOV_EAX_ATOM( unbound ); REM( "set no result" );
1562 }
void asm_set_output_status ( context_t ctx,
int  n 
)
Parameters
ctxcompilation context
noutput status

Generates code to set output/stop status in EBX

Generated code: mov ebx,n

Definition at line 1575 of file i386.c.

1576 {
1577  MOV_EBX_CONST( n );
1578 }
int asm_catch_prologue ( context_t ctx)
Parameters
ctxcompilation context
Returns
catch exit address

Generates prologue code for the catch command. Prologue is the code which stands right before the code for the body of the catch. The prologue is a trampoline which temporarily overwrited the default function exit address. Thus, all exits done in the commands of the catch are directed to this trampoline.

Note! This function changes the exit_addr to point to jump_addr!

Generated code: jmp $1 jump_addr: jmp catch_epilogue $1: {body}

Definition at line 1640 of file i386.c.

1641 {
1642  JMP( IP+9, TEXT("catch") ); // skip over next jump
1643  ctx->exit_addr = IP;
1644  JMP( 0, TEXT("exit_catch") ); // to be fixed later
1645 
1646  INFO( "" );
1647  asm_label( ctx, TEXT("catch:") );
1648  INFO( "start of catch block" );
1649 
1650  return LOCAL_IP-4;
1651 }
void asm_catch_epilogue ( context_t ctx)
Parameters
ctxcompilation context

Generates epilogue code for the catch command. It fixes unset branch in the prologue and generates code which captures and verifies the result of the monitored block of commands.

Generated code: push {tag} ; already done push {eax} ; already done call rt_catchchk mov ebx,[catch_output_flag] cmp ebx,1 je exit push eax

Definition at line 1673 of file i386.c.

1674 {
1675  INFO( "" );
1676  INFO( "check result of catch block" );
1677 
1678  PUSH_EBX;
1679  CALL( rt_catchchk, TEXT("rt_catchchk") );
1681  CMP_EBX_CONST(1);
1682  JE_EXIT;
1683 
1684 //__asm__ volatile ("int $3; nop");
1685 
1686  PUSH_EAX;
1687 }
void asm_goto ( context_t ctx,
atom_t  tag 
)
Parameters
ctxcompilation context
tagtag for the target address

Generates unconditional jump to a given address specified by a tag variable.

Generated code: jmp addr

Definition at line 1702 of file i386.c.

1703 {
1704  if( ctx->generate )
1705  {
1706  #ifdef SAFEMODE
1707  assert( IS_INTEGER(VALUE(tag)) );
1708  #endif
1709 
1710  JMP_ATOM( START_IP+INTEGER(VALUE(tag)), NAME(tag) );
1711  }
1712  else
1713  {
1714  JMP( 0, TEXT("") );
1715  }
1716 }
void asm_goto_prologue ( context_t ctx,
atom_t  source 
)
Parameters
ctxcompilation context
sourcesource of the function

Generates code to push the source. It will be used by rt_goto().

Generated code:

push {source}

Definition at line 1731 of file i386.c.

1732 {
1733  PUSH_SOURCE( source ); REM( "source" );
1734 }
void asm_goto_epilogue ( context_t ctx,
atom_t  source 
)
Parameters
ctxcompilation context
sourcesource of goto command

Generates epilogue for goto command which input cannot be resolve at compile time.

The epilogue generates code to find the target address of the goto command. The code assumes that EAX contains an integer atom with the target address.

Generated code:

{expr} ; already generated cmp [eax+OFFSET_ID],ERROR_ID je exit

push eax ; tag mov eax,[eax+INTEGER] ; EAX=target call deuse ; tag

add eax,{base} jmp eax

Definition at line 1763 of file i386.c.

1764 {
1765  CMP_ID_ERROR; REM( "exit if error" );
1766  JE_EXIT;
1767 
1768  PUSH_EAX; REM( "get target relative address" );
1770  CALL( deuse, TEXT("deuse") );
1771 
1772  ADD_EAX_CONST_4( START_IP ); REM( "make it absolute" );
1773  JMP_EAX( source );
1774 }
int asm_test_prologue ( context_t ctx,
int  criteria 
)
Parameters
ctxcompilation context
criteriaiftrue=1, iffalse=0
Returns
address of branch to skip over iftrue/iffalse

Generates prologue code for the iftrue or the iffalse command (depending on the value of criteria parameter). Prologue is used to skip the body if the criyeria is not fulfilled.

The return value of the function is the address of the instruction where a fix-up is needed.

Generated code:

cmp [ebp+OFFSET_TEST],criteria jne skip

Definition at line 1796 of file i386.c.

1797 {
1798  CMP_MEM_EBP( BASE_OFFSET_TEST, criteria ); REM( "check test result" );
1799  JNE( 0, TEXT("skip") );
1800 
1801  return LOCAL_IP-4;
1802 }
void asm_run_epilogue ( context_t ctx)
Parameters
ctxcompilation context

Generates epilogue for runmacro command which does the actual execution of commands.

The epilogue generates code to get the address of compiled code and execute it.

Generated code:

{run} ; already generated cmp [eax+OFFSET_ID],ERROR_ID je exit

push eax ; EAX=var atom mov eax,[eax+DESCR1] ; get DESCR1 which contains the address call [eax+ADDRESS] ; code to run, EAX=result of run code call deuse ; deuse var atom (including run code)

cmp ebx,1 je exit

cmp eax,{stopped} je exit

Definition at line 1832 of file i386.c.

1833 {
1834  INFO( "" );
1835  INFO( "actual execution of run" );
1836 
1837  CMP_ID_ERROR; REM( "exit if error" );
1838  JE_EXIT;
1839 
1840  MOV_ESI_EBP; REM( "static link" );
1841  PUSH_EAX; REM( "EAX=var atom" );
1842  MOV_EAX_MEM_EAX( OFFSET_DESCR1 ); REM( "EAX=var descriptor" );
1843 
1844  CALL_MEM_EAX( OFFSET_ADDRESS, TEXT("ADDRESS") ); REM( "get and call var address" );
1845 
1846  CALL( deuse, TEXT("deuse") );
1847 
1848  CMP_EBX_CONST( 1 );
1849  JE_EXIT;
1850 
1851  CMP_EAX_ATOM(stopped); REM( "exit if stopped" );
1852  JE_EXIT;
1853 }
void asm_runresult_epilogue ( context_t ctx)
Parameters
ctxcompilation context

Generates epilogue for runresult command which does the actual execution of commands.

The epilogue generates code to get the address of compiled code and execute it. It reuses code generated by asm_run_epilogue().

Generated code:

{run} ; already generated cmp [eax+OFFSET_ID],ERROR_ID je skip

push eax ; EAX=var atom mov eax,[eax+DESCR1] ; get DESCR1 which contains the address call [eax+ADDRESS] ; code to run, EAX=result of run code call deuse ; deuse var atom (including run code) skip: push eax call rt_runresult_fix

Definition at line 1882 of file i386.c.

1883 {
1884  INFO( "" );
1885  INFO( "actual execution of runresult" );
1886 
1887  CMP_ID_ERROR; REM( "skip if error" );
1888  JE( 0, TEXT("$skip") );
1889  int branch=LOCAL_IP-4;
1890 
1891  MOV_ESI_EBP; REM( "static link" );
1892  PUSH_EAX; REM( "EAX=var atom" );
1893  MOV_EAX_MEM_EAX( OFFSET_DESCR1 ); REM( "EAX=var descriptor" );
1894 
1895  CALL_MEM_EAX( OFFSET_ADDRESS, TEXT("ADDRESS") ); REM( "get and call var address" );
1896 
1897  CALL( deuse, TEXT("deuse") );
1898 
1899 LABEL( "$skip:" );
1900  asm_fix( ctx, branch );
1901 
1902  PUSH_EAX;
1903  CALL( rt_runresult_fix, TEXT("rt_runresult_fix") );
1904 }
int asm_for_prologue ( context_t ctx,
atom_t  step_var,
atom_t  source,
int *  branch2 
)
Parameters
ctxcompilation context
step_varvariable which will hold the value of FOR's step
sourcesource of the expression
branch2address of branch to skip over the whole repeat
Returns
branch address

Generates prologue code for the for command.

The prologue generates code to calculate the actual number of repetitions. It checks whether there was an error during calculation. If not, it checks whether the number of repetitions is valid. Finally the prologue initializes the for by calling rt_repeat_enter to set up a new element of the repeat chain.

The return value of the function is the address of the instruction right after the prologue. This address is used by asm_for_epilogue() and is absolute address.

Generated code:

{expr_from} {expr_to} {expr_step} push {addr of step_var's value} push {source} call rt_forchk cmp [eax+OFFSET_ID],ERROR_ID je exit

push eax mov [eax+REPLIMIT],eax call deuse

cmp eax,0 je skip_for ][ ; <-branch2

push eax push ebp call rt_repeat_enter $for:

Definition at line 1957 of file i386.c.

1958 {
1959 
1960  asm_push_value_addr( ctx, step_var );
1961 
1962  INFO( "" );
1963  INFO( "check validity of for count" );
1964  PUSH_SOURCE( source ); REM( "source" );
1965  CALL( rt_forchk, TEXT("rt_forchk") ); REM( "exit if invalid" );
1966  CMP_ID_ERROR;
1967  JE_EXIT;
1968 
1969  PUSH_EAX; REM( "free for count expression" );
1970  MOV_EAX_MEM_EAX( OFFSET_INT ); REM( "get for count" );
1971  CALL( deuse, TEXT("deuse") );
1972 
1973  CMP_EAX_CONST( 0 ); REM( "exit if it is 0" );
1974  JE( 0, TEXT("skip_for") );
1975  *branch2 = LOCAL_IP-4;
1976 
1977  PUSH_EAX; REM( "for count" );
1978  PUSH_EBP; REM( "static link" );
1979  CALL( rt_repeat_enter, TEXT("rt_repeat_enter") ); REM( "initialize for" ); // reuse rt_repeat_enter
1980 
1981  asm_label( ctx, TEXT("$for:") );
1982 
1983  return IP;
1984 }
void asm_for_epilogue ( context_t ctx,
int  branch,
int  branch2 
)
Parameters
ctxcompilation context
branchbranch for for's loop
branch2branch for skipping for

Generates epilogue code for the for command.

The epilogue of for decrements the repeat count and if it is not zero, then loops back to the branch address, which is provided as parameter.

branch2 contains the address where a branch is made over the whole body of the for when the repetition number is 0.

Generated code: (note: {body} is not a part of the epilogue)

$for: {body} mov eax,[ebp+REPEATCHAIN] mov eax,[eax+CAR_OFFSET] inc [eax+REPCOUNT] dec [eax+REPLIMIT] jnz $for

$skip: push ebp call rt_repeat_exit // reuses repeat_exit

Definition at line 2025 of file i386.c.

2026 {
2027 
2028  INFO( "" );
2029  INFO( "calculate next loop of for" );
2030  MOV_EAX_MEM_EBP( BASE_OFFSET_REPEATCHAIN ); REM( "get repeat chain" );
2031  MOV_EAX_MEM_EAX( CAR_OFFSET ); REM( "get current repeat node" );
2032  INC_EAX_MEM( OFFSET_REPCOUNT ); REM( "increase done repeats" );
2033  DEC_EAX_MEM( OFFSET_REPLIMIT ); REM( "decrease left repeats" );
2034 
2035  //PUSH_MEM_EBP(BASE_OFFSET_REPEATCHAIN);
2036  //PUSH_MEM_EAX(OFFSET_REPCOUNT);
2037  //PUSH_MEM_EAX(OFFSET_REPLIMIT);
2038  //CALL( rt_repeat_debug, TEXT("") );
2039 
2040  JNZ( branch, TEXT("$for") );
2041 
2042  if( branch2!=-1 )
2043  {
2044  INFO( "" );
2045  asm_label( ctx, TEXT("skip_for:") );
2046  INFO( "no more loops" );
2047  asm_fix( ctx, branch2 );
2048  }
2049 
2050  PUSH_EBP; REM( "static link" );
2051  CALL( rt_repeat_exit, TEXT("rt_repeat_exit") ); // same as exit from repeat
2052 }
void asm_external_function ( context_t ctx,
atom_t  func 
)
Parameters
ctxcompilation context
funcfunction which trampoline to generate

Generates a trampoline to call an external function. The trampoline's code converts Logo parameters into C-type data and prepares the stack to be as expected by a sdtcall function.

Generated code:

func: push ebp mov ebp,esp

; clear error flag mov [error_flag],0

; for each parameter do: push [ebp+{ofs}] ; push param call atom_to_xxx ; convert to c-type push edx ; push c-type hi word (if 64-bit) push eax ; push c-type lo word fstp [esp] ; store 32- or 64-bit fp number to stack

call func

; check error flag cmp [error_flag],0 je ok mov eax,[error_flag] jmp exit

; push result ok: push edx ; push c-type hi word (if 64-bit) push eax ; push c-type lo word fstp [esp] ; store 32- or 64-bit fp number to stack call xxx-to_atom ; convert back to atom

exit: mov esp,ebp pop ebp ret

Definition at line 2103 of file i386.c.

2104 {
2105  INFO( "" );
2106  INFO( "=========================" );
2107  INFO( " EXTERNAL FUNCTION %a", NAME(func) );
2108  INFO( "=========================" );
2109  INFO( "" );
2110 
2111  LABEL( "%a:", NAME(func) );
2112  PUSH_EBP; REM( "function prologue" );
2113  MOV_EBP_ESP;
2114 
2115  INFO( "" );
2117  REM( "clear error flag" );
2118  INFO( "" );
2119 
2120  INFO( "convert parameters to C-types" );
2121 
2122  atom_t params;
2123  for( params=LOCALS(func); IS_NOT_EMPTY(params); params=CDR(params) )
2124  {
2125  atom_t param = CAR(params);
2126  if( !IS_EXTERNAL(param) ) continue;
2127 
2128  int c_type = VARCLASS( param );
2129 
2130  // push param's atom and convert it to c-type
2131  PUSH_MEM_EBP( OFFSET(param) ); REM( "convert %a", NAME(param) );
2132  CALL( c_types[c_type].atom_to_c, c_types[c_type].atom_to_c_name );
2133 
2134  // push the result to the stack. If the result is 1..32 bits, then
2135  // it is in EAX. If it is 33..64 bits, then it is stored in EDX:EAX.
2136  if( c_types[c_type].size>32 ) { PUSH_EDX; }
2137  PUSH_EAX;
2138 
2139  // floating-point numbers are stored in FPU's st0 register.
2140  // Pop the value from the register and store it in the stack.
2141  if( c_types[c_type].class==C_TYPE_FLOAT )
2142  {
2143  if( c_types[c_type].size>32 )
2144  { FSTPD_MEM_ESP; } // store 64-bit float
2145  else
2146  { FSTPF_MEM_ESP; } // store 32-bit float
2147  }
2148  } //params=LOCALS(func)
2149 
2150  INFO( "" );
2151  INFO( "call to external function" );
2152  CALL_ATOM( ADDRESS(func), NAME(func) );
2153 
2154  INFO( "" );
2155  INFO( "check error flag" );
2156 
2158  JE( 0, TEXT("$ok") ); REM( "continue if no error" );
2159  int branch=LOCAL_IP-4;
2161  JMP( 0, TEXT("exit") );
2162  int branch2=LOCAL_IP-4;
2163 
2164  // function result must be converted back into atom
2165  INFO( "" );
2166  INFO( "convert function result" );
2167 LABEL( "$ok:" );
2168  asm_fix( ctx, branch );
2169  int c_type = VARCLASS( func );
2170  if( c_types[c_type].size>32 ) { PUSH_EDX; }
2171  PUSH_EAX;
2172  if( c_types[c_type].class==C_TYPE_FLOAT )
2173  {
2174  if( c_types[c_type].size>32 )
2175  { FSTPD_MEM_ESP; } // store 64-bit float
2176  else
2177  { FSTPF_MEM_ESP; } // store 32-bit float
2178  }
2179  CALL( c_types[c_type].c_to_atom, c_types[c_type].c_to_atom_name );
2180  INFO( "" );
2181 
2182  // fix the stack by removing all c-type data
2183  // (actually this is not needed, because the
2184  // next MOV ESP,EBP command fixes the stack
2185 LABEL( "exit:" );
2186  asm_fix( ctx, branch2 );
2187  MOV_ESP_EBP;
2188  POP_EBP;
2189  RET; REM( "end of %a", NAME(func) );
2190 }
void asm_internal_function ( context_t ctx,
int  static_link,
atom_t  func 
)
Parameters
ctxcompilation context
static_linkstatic link from the current frame
funcfunction which trampoline to generate

Generates a trampoline to call an external function. The trampoline's code converts Logo parameters into C-type data and prepares the stack to be as expected by a sdtcall function.

Generated code:

func:

exit: ret

Definition at line 2214 of file i386.c.

2215 {
2216  //INT_3;
2217  INFO( "" );
2218  INFO( "=========================" );
2219  INFO( " INTERNAL FUNCTION %a", NAME(func) );
2220  INFO( "=========================" );
2221  INFO( "" );
2222  asm_prologue( ctx, func, 0 );
2223 
2224  INFO( "convert parameters to atoms" );
2225  atom_t params;
2226  int offset = 8; // this is offset from a C calling code
2227  int count = 0;
2228  for( params = LOCALS(func); IS_NOT_EMPTY(params); params=CDR(params))
2229  {
2230  atom_t param = CAR( params );
2231  if( !IS_INTERNAL(param) ) continue;
2232  int c_type = VARCLASS( param );
2233 
2234  PUSH_MEM_EBP( offset );
2235  CALL( c_types[c_type].c_to_atom, c_types[c_type].c_to_atom_name );
2236  PUSH_EAX;
2237  offset += c_types[c_type].size/8;
2238  count++;
2239  }
2240 
2241  PUSH_CONST( count );
2242 
2243  //MOV_EBP_CONST( static_link );
2244  //MOV_ESI_CONST( static_link );
2247  MOV_ESI_EBP;
2248  INFO( "" );
2249  INFO( "call to internal function" );
2250  //INT_3;
2251  CALL_ATOM( ADDRESS(func), NAME(func) );
2253 
2254  CMP_ID_ERROR;
2255  JNE( 0, TEXT("$skip") );
2256  int branch = LOCAL_IP-4;
2257  MOV_MEM_OFS_EAX( &error_flag ); REM( "store result in error flag");
2258  asm_fix( ctx, branch );
2259 LABEL( "$skip" );
2260 
2261  INFO( "" );
2262  INFO( "convert function result" );
2263  int c_type = VARCLASS( func );
2264  PUSH_EAX;
2265  PUSH_EAX;
2266  CALL( c_types[c_type].atom_to_c, c_types[c_type].atom_to_c_name );
2267  INFO( "" );
2268  CALL( deuse, TEXT("deuse result") );
2269 
2270  POP_EDX;
2271  for( params=LOCALS(func); IS_NOT_EMPTY(params); params=CDR(params) )
2272  if( IS_INTERNAL(CAR(params)) )
2273  CALL( deuse, TEXT("deuse") );
2274 
2275  //INT_3;
2276  asm_epilogue( ctx, func, COMPILE_AS_NON_MACRO );
2277 }
void asm_int_3 ( context_t ctx)
Parameters
ctxcompilation context

Generates instruction for trapping debugger.

Generated code:

int 3

Definition at line 2294 of file i386.c.

2295 {
2296  INT_3;
2297 }
void asm_nop ( context_t ctx)
Parameters
ctxcompilation context

Generates instruction for no operation.

Generated code:

nop

Definition at line 2312 of file i386.c.

2313 {
2314  NOP;
2315 }

[ HOME | INDEX | ATOMS | VARS | REFERENCE ]
Lhogho Developer's Documentation
Wed Jul 10 2013