Lhogho
0.0.028
|
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... | |
#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_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 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]"); } |
ctx | compilation context |
addr | target address |
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.
ctx | compilation context |
func | function which prologue to generate |
check | add 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.
ctx | compilation context |
func | function which epilogue to generate |
is_macro | if 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.
ctx | compilation context |
atom | atom 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.
Generated code:
push {atom} call {use} ; if not UNBOUND or EMPTY LIST
ctx | compilation context |
source | source 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.
ctx | compilation context |
source | source 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.
ctx | compilation context |
var | var to which link is sought |
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.
ctx | compilation context |
var | variable which value is referenced |
source | source of var reference |
check | if 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.
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.
ctx | compilation context |
var | variable 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.
ctx | compilation context |
var | atom to call |
params | number 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):
Generated code (for functions with variable number of inputs or not-primitive):
Definition at line 775 of file i386.c.
ctx | compilation 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
ctx | compilation context |
source | source of the OUTPUT command |
true_output | flag 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.
ctx | compilation context |
source | source 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.
int asm_if_prologue | ( | context_t * | ctx) |
ctx | compilation context |
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.
int asm_if_epilogue | ( | context_t * | ctx) |
ctx | compilation context |
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
ctx | compilation context |
addr | address of data to fix |
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).
int asm_repeat_prologue_const | ( | context_t * | ctx, |
int | cnt | ||
) |
ctx | compilation context |
cnt | number of repetitions |
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
ctx | compilation context |
source | source of the expression |
branch2 | address of branch to skip over the whole repeat |
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.
ctx | compilation context |
branch | branch for repeat's loop |
branch2 | branch 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.
int asm_forever_prologue | ( | context_t * | ctx) |
ctx | compilation context |
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:
ctx | compilation context |
branch | branch 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.
ctx | compilation 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
ctx | compilation context |
mode | mode 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.
ctx | compilation 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
int asm_while_prologue | ( | context_t * | ctx, |
int | is_while, | ||
int | is_do | ||
) |
ctx | compilation context |
is_while | while=1, until=0 |
is_do | do.while&do.until=1, while&until=0 |
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.
ctx | compilation context |
loop_branch | branch for while/until's loop |
skip_branch | branch to skip while/until |
is_while | while=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.
ctx | compilation context |
n | output status |
Generates code to set output/stop status in EBX
Generated code: mov ebx,n
int asm_catch_prologue | ( | context_t * | ctx) |
ctx | compilation context |
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}
ctx | compilation 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.
ctx | compilation context |
tag | tag for the target address |
Generates unconditional jump to a given address specified by a tag variable.
Generated code: jmp addr
ctx | compilation context |
source | source of the function |
Generates code to push the source. It will be used by rt_goto().
Generated code:
push {source}
ctx | compilation context |
source | source 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.
int asm_test_prologue | ( | context_t * | ctx, |
int | criteria | ||
) |
ctx | compilation context |
criteria | iftrue=1, iffalse=0 |
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.
ctx | compilation 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.
ctx | compilation 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.
ctx | compilation context |
step_var | variable which will hold the value of FOR's step |
source | source of the expression |
branch2 | address of branch to skip over the whole repeat |
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.
ctx | compilation context |
branch | branch for for's loop |
branch2 | branch 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.
ctx | compilation context |
func | function 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.
ctx | compilation context |
static_link | static link from the current frame |
func | function 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.