Lhogho  0.0.028
 All Data Structures Files Functions Variables Typedefs Macros Pages
i386.c
Go to the documentation of this file.
1 //
2 // Project: Lhogho
3 // File: i386.c
4 //
5 // Copyright (C) 2007 P.Boytchev
6 //
7 // Revision history:
8 // 2007-06-19 - file created
9 // 2007-08-05 - asm_result_make()
10 // 2007-08-08 - asm_reference()
11 // 2007-08-09 - Fixed bug #1771163 Warning building the dev docs
12 // 2007-08-12 - Fixed bug #1767825 Bad return value for empty programs
13 // 2007-08-13 - Support for primitive variables
14 // - Fixed bug #1773113 MAKE does not work with primitive variables
15 // 2007-09-03 - Fixed bug #1787023 ARCTAN and RADARCTAN
16 // 2007-09-18 - Support for OUTPUT and STOP
17 // 2007-09-23 - Support for IF
18 // 2007-10-21 - Support for REPEAT, FOREVER
19 // 2007-11-04 - Support for WHILE, UNTIL
20 // 2007-11-09 - Fixed bug #1828215 MAKE does not work with unknown variables
21 // - Fixed bug #1828217 ':' does not work with unknown variables
22 // 2007-12-23 - Support for RUN
23 // 2008-01-07 - Fixed bug #1856864 Defined but unset variables
24 // - Support for RUNRESULT
25 // 2009-08-03 - Fixed bug #2191139 Errors/exits in internal functions
26 // 2009-08-16 - Fixed bug #2838617 RUN suppresses STOP
27 // 2009-08-18 - EBX=1 value from output/stop; EBX=0 value from expression
28 // 2009-08-19 - Support for MAYBEOUTPUT
29 // 2011-02-05 - Fixed bug #3173377 Warnings building developer's documentation
30 // 2011-03-03 - Fixed bug #3197053 DO.UNTIL behaves exactly like UNTIL
31 // - Fixed bug #3197052 DO.WHILE behaves exactly like WHILE
32 // 2011-10-14 - Support for RUNMACRO
33 // 2011-12-31 - Fixed bug #3466110 Error in SE's input cases a crash
34 // 2012-01-02 - Command-line options are translatable
35 // 2012-02-26 - Fixed bug #3493871 Externals do not capture errors
36 //
37 //
38 // This program is free software; you can redistribute it and/or modify
39 // it under the terms of the GNU General Public License as published by
40 // the Free Software Foundation; either version 2 of the License, or
41 // (at your option) any later version.
42 //
43 // This program is distributed in the hope that it will be useful,
44 // but WITHOUT ANY WARRANTY; without even the implied warranty of
45 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46 // GNU General Public License for more details.
47 //
48 // You should have received a copy of the GNU General Public License
49 // along with this program; if not, write to the Free Software
50 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
51 //
52 
53 
54 #include "stdio.h"
55 #include "atoms.h"
56 #include "words.h"
57 #include "vars.h"
58 #include "lists.h"
59 #include "numbers.h"
60 #include "unicode.h"
61 #include "options.h"
62 #include "runtime.h"
63 #include "asm.h"
64 
65 
66 #define EXIT (void*)ctx->exit_addr
67 #define START_IP (ctx->generate?(int)MEMORY(ctx->generate):0)
68 #define LOCAL_IP (ctx->size)
69 #define IP START_IP+LOCAL_IP
70 #define REL(addr) relative( ctx, (uint_t)addr )
71 
72 #define EMIT1(a) emit_1(ctx,a)
73 #define EMIT2(a) emit_2(ctx,a)
74 #define EMIT3(a,b) emit_2(ctx,a); emit_1(ctx,b)
75 #define EMIT4(a) emit_4(ctx,a)
76 #define EMIT5(a,b) emit_1(ctx,a); emit_4(ctx,(uint_t)b)
77 #define EMIT6(a,b) emit_2(ctx,a); emit_4(ctx,(uint_t)b)
78 
79 //===================================================
91 //===================================================
92 uint_t relative( context_t* ctx, int addr )
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 }
102 
103 //===================================================
110 //===================================================
111 void asm_label( context_t* ctx, chars_t label )
112 {
113  #ifdef ADVANCED
114  disasm( ctx, 4, label );
115 #endif //ADVANCED
116 }
117 
118 #define PUSH_EAX { EMIT1(0x50); INSTR("push eax"); }
119 #define PUSH_EDX { EMIT1(0x52); INSTR("push edx"); }
120 #define PUSH_EBP { EMIT1(0x55); INSTR("push ebp"); }
121 #define PUSH_ESI { EMIT1(0x56); INSTR("push esi"); }
122 #define PUSH_EBX { EMIT1(0x53); INSTR("push ebx"); }
123 
124 #define POP_EAX { EMIT1(0x58); INSTR("pop eax"); }
125 #define POP_EDX { EMIT1(0x5A); INSTR("pop edx"); }
126 #define POP_EBP { EMIT1(0x5D); INSTR("pop ebp"); }
127 #define POP_ESI { EMIT1(0x5E); INSTR("pop esi"); }
128 #define POP_EBX { EMIT1(0x5B); INSTR("pop ebx"); }
129 
130 #define PUSH_MEM_EAX(ofs) { EMIT6(0xB0FF,ofs); INSTR("push [eax%p]",ofs); }
131 #define PUSH_MEM_EBP(ofs) { EMIT6(0xB5FF,ofs); INSTR("push [ebp%p]",ofs); }
132 #define PUSH_MEM_ESI(ofs) { EMIT6(0xB6FF,ofs); INSTR("push [esi%p]",ofs); }
133 
134 #define PUSH_MEM(ofs) { EMIT6(0x35FF,ofs); INSTR("push [%d]",ofs); }
135 
136 #define PUSH_SOURCE(s) { EMIT5(0x68,s); INSTR("push (%l)",s); }
137 #define PUSH_CONST(n) { EMIT5(0x68,n); INSTR("push %d",n); }
138 #define PUSH_ATOM(a) { EMIT5(0x68,a); INSTR("push %a",a); }
139 #define PUSH_ATOMSTR(a,s) { EMIT5(0x68,a); INSTR("push %s",s); }
140 
141 #define MOV_EAX_ATOM(atom) { EMIT5(0xB8,atom); INSTR("mov eax,%a",atom); }
142 #define MOV_ESI_CONST(n) { EMIT5(0xBE,n); INSTR("mov esi,%d",n); }
143 #define MOV_ESI_CONST(n) { EMIT5(0xBE,n); INSTR("mov esi,%d",n); }
144 #define MOV_EBX_CONST(n) { EMIT5(0xBB,n); INSTR("mov ebx,%d",n); }
145 
146 #define MOV_EAX_EBP { EMIT2(0xE889); INSTR("mov eax,ebp"); }
147 #define MOV_EBP_ESP { EMIT2(0xE589); INSTR("mov ebp,esp"); }
148 #define MOV_ESP_EBP { EMIT2(0xEC89); INSTR("mov esp,ebp"); }
149 #define MOV_ESI_EBP { EMIT2(0xEE89); INSTR("mov esi,ebp"); }
150 
151 #define MOV_EAX_MEM_ESP { EMIT3(0x048B,0x24); INSTR("mov eax,[esp]"); }
152 #define MOV_EAX_MEM_EBP(ofs) { EMIT3(0x458B,ofs); INSTR("mov eax,[ebp%p]",ofs); }
153 #define MOV_EAX_MEM_EAX(ofs) { EMIT3(0x408B,ofs); INSTR("mov eax,[eax%p]",ofs); }
154 #define MOV_EAX_MEM_OFS(ofs) { EMIT6(0x058B,ofs); INSTR("mov eax,[%d]",ofs); }
155 #define MOV_EBP_MEM_OFS(ofs) { EMIT6(0x2D8B,ofs); INSTR("mov ebp,[%d]",ofs); }
156 #define MOV_EBX_MEM_OFS(ofs) { EMIT6(0x1D8B,ofs); INSTR("mov ebp,[%d]",ofs); }
157 
158 #define MOV_MEM_EBP_EAX(ofs) { EMIT6(0x8589,ofs); INSTR("mov [ebp%p],eax",ofs); }
159 #define MOV_MEM_ESI_EAX(ofs) { EMIT6(0x8689,ofs); INSTR("mov [esi%p],eax",ofs); }
160 #define MOV_MEM_OFS_EAX(ofs) { EMIT6(0x0589,ofs); INSTR("mov [%d],eax",ofs); }
161 #define MOV_MEM_OFS_EBP(ofs) { EMIT6(0x2D89,ofs); INSTR("mov [%d],ebp",ofs); }
162 #define MOV_MEM_OFS_CONST(ofs,n) {EMIT6(0x05C7,ofs); EMIT4(n); \
163  INSTR("mov [%d],%a", ofs, n); }
164 
165 #define MOV_ESI_SSMEM_ESI_4 { EMIT4(0xFC768B36); INSTR("mov esi,ss:[esi-4]"); }
166 #define MOV_ESI_SSMEM_EBP_4 { EMIT4(0xFC758B36); INSTR("mov esi,ss:[ebp-4]"); }
167 
168 #define INC_EAX_MEM(n) { EMIT3(0x40FF,n); INSTR("inc [eax%p]",n); }
169 #define DEC_EAX_MEM(n) { EMIT3(0x48FF,n); INSTR("dec [eax%p]",n); }
170 
171 #define RET { EMIT1(0xC3); INSTR("ret"); }
172 
173 #define ADD_EAX_CONST_4(n) { EMIT5(0x05,n); INSTR("add eax,%d",n); }
174 #define ADD_ESI_CONST_4(n) { EMIT6(0xC681,n); INSTR("add esi,%d",n); }
175 
176 #define CMP_EBX_CONST(n) { EMIT3(0xFB83,n); INSTR("cmp ebx,%d",n); }
177 #define CMP_EAX_CONST(n) { EMIT5(0x3D,n); INSTR("cmp eax,%d",n); }
178 #define CMP_EAX_ATOM(a) { EMIT5(0x3D,a); INSTR("cmp eax,%l",a); }
179 #define CMP_ID_ERROR { EMIT2(0x7880); EMIT1(OFFSET_ID); EMIT1(ERROR_ID);\
180  INSTR("cmp [eax+ID],ERROR_ID"); }
181 #define CMP_MEM_EBP(ofs,val) { EMIT2(0x7D80); EMIT1(ofs); EMIT1(val);\
182  INSTR("cmp [eax%p],%d",ofs,val); }
183 #define CMP_MEM_OFS_CONST_4(ofs,n) { EMIT6(0x3D81,ofs); EMIT4(n); INSTR("cmp [%d],%a", ofs, n); }
184 #define CMP_MEM_OFS_CONST_1(ofs,n) { EMIT6(0x3D80,ofs); EMIT1(n); \
185  INSTR("cmp [%d],%d", ofs, n); }
186 
187 //#define JC_EXIT { EMIT6(0x820F,REL(EXIT)); INSTR("jc exit"); }
188 #define JE_EXIT { EMIT6(0x840F,REL(EXIT)); INSTR("je exit"); }
189 #define JE(addr,name) { EMIT6(0x840F,REL(addr)); INSTR("je %s",name); }
190 #define JNE(addr,name) { EMIT6(0x850F,REL(addr)); INSTR("jne %s",name); }
191 #define JNZ(addr,name) { EMIT6(0x850F,REL(addr)); INSTR("jnz %s",name); }
192 
193 #define JMP_EXIT { EMIT5(0xE9,REL(EXIT)); INSTR("jmp exit"); }
194 #define JMP(addr,name) { EMIT5(0xE9,REL(addr)); INSTR("jmp %s",name); }
195 #define JMP_ATOM(addr,name) { EMIT5(0xE9,REL(addr)); INSTR("jmp %a",name); }
196 #define JMP_EAX(name) { EMIT2(0xE0FF); INSTR("jmp %a",name); }
197 
198 #define CALL(addr,name) { EMIT5(0xE8,REL(addr)); INSTR("call %s",name); }
199 #define CALL_ATOM(addr,name) { EMIT5(0xE8,REL(addr)); INSTR("call %a",name); }
200 
201 #define CALL_MEM(addr,name) { EMIT6(0x15FF,addr); INSTR("call [%a]",name); }
202 #define CALL_MEM_EAX(addr,name) { EMIT6(0x90FF,addr); INSTR("call [eax+%s]",name); }
203 
204 #define FSTPF_MEM_ESP { EMIT2(0x1CD9); EMIT1(0x24); INSTR("fstpf [esp]"); } // FSTP for float
205 #define FSTPD_MEM_ESP { EMIT2(0x1CDD); EMIT1(0x24); INSTR("fstpd [esp]"); } // FSTP for double
206 
207 #define INT_3 { EMIT1(0xCC); INSTR("int 3"); }
208 #define NOP { EMIT1(0x90); INSTR("nop"); }
209 //#define STC { EMIT1(0xF9); INSTR("stc"); }
210 //#define CLC { EMIT1(0xF8); INSTR("clc"); }
211 
212 //===================================================
246 
247 //===================================================
248 void asm_prologue( context_t* ctx, atom_t func, int check )
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 }
307 
308 //===================================================
341 //===================================================
343 {
344  MOV_EBX_CONST(0);
345 }
346 void asm_epilogue( context_t* ctx, atom_t func, int is_macro )
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 }
385 
386 
387 //===================================================
407 //===================================================
408 void asm_push_atom( context_t* ctx, atom_t atom )
409 {
410  PUSH_ATOM( atom );
411  if( !IS_UNBOUND(atom) && !IS_EMPTY(atom) )
412  {
413  CALL( use, TEXT("use") );
414  }
415 }
416 
417 //===================================================
427 //===================================================
429 {
430  CALL( deuse, TEXT("deuse") );
431 }
432 
433 //===================================================
443 //===================================================
445 {
446  POP_EDX;
447 }
448 
449 //===================================================
459 //===================================================
461 {
462  PUSH_EAX; REM( "move result in stack " );
463 }
464 
465 //===================================================
476 //===================================================
477 void asm_result_proc( context_t* ctx, atom_t source )
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 }
487 
488 //===================================================
497 //===================================================
498 void asm_result_unknown( context_t* ctx, atom_t source )
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 }
505 
506 //===================================================
517 //===================================================
518 void asm_result_func( context_t* ctx, atom_t source )
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 }
526 
527 //===================================================
544 //===================================================
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 }
558 
559 //===================================================
567 //===================================================
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 }
580 
581 //===================================================
618 //===================================================
619 void asm_reference( context_t* ctx, atom_t var, atom_t source, int check )
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 }
644 
645 //===================================================
659 
683 //===================================================
684 void asm_make_direct( context_t* ctx, atom_t var, atom_t source )
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 }
721 
722 //===================================================
740 //===================================================
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 }
756 
757 //===================================================
774 //===================================================
775 void asm_call_atom( context_t* ctx, atom_t var, int params )
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 }
848 
849 
850 //===================================================
865 //===================================================
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 }
875 
876 //===================================================
885 //===================================================
886 void asm_dump_source( context_t* ctx, atom_t source )
887 {
888  INFO( "" );
889  PUSH_SOURCE( source ); REM( "dump source" );
890  CALL( rt_predump, TEXT("rt_predump") );
891  INFO( "" );
892 }
893 
894 //===================================================
906 //===================================================
908 {
909  INFO( "" );
910  MOV_EAX_ATOM( unbound ); REM( "there is no result" );
911 }
912 
913 //===================================================
929 //===================================================
930 void asm_output( context_t* ctx, atom_t source, int true_output )
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 }
947 
948 //===================================================
961 //===================================================
962 void asm_stop( context_t* ctx, atom_t source )
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 }
978 
979 //===================================================
998 //===================================================
999 void asm_boolean( context_t* ctx, atom_t source )
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 }
1008 
1009 //===================================================
1033 //===================================================
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 }
1040 
1041 //===================================================
1055 //===================================================
1057 {
1058  JMP( 0, TEXT("ifend") ); REM( "skip if-else block" );
1059  return LOCAL_IP-4;
1060 }
1061 
1062 //===================================================
1077 //===================================================
1078 void asm_fix( context_t* ctx, int addr )
1079 {
1080  reemit_4( ctx, addr, ctx->size-addr-4 );
1081 }
1082 
1083 //===================================================
1109 //===================================================
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 }
1122 
1123 //===================================================
1168 //===================================================
1169 int asm_repeat_prologue_expr( context_t* ctx, atom_t source, int* branch2 )
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 }
1194 
1195 //===================================================
1232 //===================================================
1233 //void rt_repeat_debug ( int replefts, int repcount, atom_t data )
1234 //{
1235 // printf("atom=");dump_atom(data,1);
1236 // printf("repcount=%d/%d replefts=%d/%d\n",repcount,REPCOUNT(CAR(data)),replefts,REPLIMIT(CAR(data)));
1237 //}
1238 
1239 void asm_repeat_epilogue( context_t* ctx, int branch, int branch2 )
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 }
1267 
1268 //===================================================
1289 //===================================================
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 }
1301 
1302 //===================================================
1319 //===================================================
1320 void asm_forever_epilogue( context_t* ctx, int branch )
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 }
1329 
1330 //===================================================
1341 //===================================================
1343 {
1344  PUSH_EBP; REM("push current frame");
1345 }
1346 
1347 //===================================================
1360 //===================================================
1362 {
1363  POP_EDX; REM( "remove pushed frame" );
1364 }
1365 
1366 //===================================================
1381 //===================================================
1382 void asm_push_mode( context_t* ctx, int mode )
1383 {
1384  PUSH_CONST( mode );
1385  if( mode==COMPILE_AS_FUNC )
1386  REM( "call as function" );
1387  else
1388  REM( "call as procedure" );
1389 }
1390 
1391 //===================================================
1403 //===================================================
1405 {
1406  MOV_EAX_ATOM( unbound ); REM( "set void result" );
1407 }
1408 
1409 //===================================================
1421 //===================================================
1423 {
1424  POP_EAX; REM( "get current result" );
1425 }
1426 
1427 
1428 //===================================================
1458 //===================================================
1459 int asm_while_prologue( context_t* ctx, int is_while, int is_do )
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 }
1477 
1478 //===================================================
1503 
1507 
1510 //===================================================
1511 int asm_while_inlogue( context_t* ctx, atom_t source, int is_while )
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 }
1529 
1530 
1531 //===================================================
1551 //===================================================
1552 void asm_while_epilogue( context_t* ctx, int loop_branch, int skip_branch, int is_while )
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 }
1563 
1564 //===================================================
1574 //===================================================
1576 {
1577  MOV_EBX_CONST( n );
1578 }
1579 
1580 
1581 //===================================================
1582 // / \fn void asm_enter_if_output( context_t* ctx )
1583 // / \brief generates enter code
1584 // / \param ctx compilation context
1585 // /
1586 // / Generates code to store EBX used by asm_exit_if_output().
1587 // /
1588 // / Generated code:
1589 // / push ebx
1590 //===================================================
1591 //void asm_enter_if_output( context_t* ctx )
1592 //{
1593 // POP_EAX;
1594 // PUSH_EBX;
1595 // PUSH_EAX;
1596 //}
1597 
1598 //===================================================
1599 // / \fn void asm_exit_if_output( context_t* ctx )
1600 // / \brief generates exit code
1601 // / \param ctx compilation context
1602 // /
1603 // / Generates code which exit if EBX shows that
1604 // / there was an active STOP or OUTPUT.
1605 // /
1606 // / Generated code:
1607 // / pop ebx
1608 // / cmp ebx,1
1609 // / je exit
1610 //===================================================
1611 //void asm_exit_if_output( context_t* ctx )
1612 //{
1613 // POP_EBX;
1614 // CMP_EBX_CONST( 1 );
1615 // JE_EXIT;
1616 //}
1617 
1618 //===================================================
1639 //===================================================
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 }
1652 
1653 //===================================================
1672 //===================================================
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 }
1688 
1689 //===================================================
1701 //===================================================
1702 void asm_goto( context_t* ctx, atom_t tag )
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 }
1717 
1718 //===================================================
1730 //===================================================
1731 void asm_goto_prologue( context_t* ctx, atom_t source )
1732 {
1733  PUSH_SOURCE( source ); REM( "source" );
1734 }
1735 
1736 //===================================================
1762 //===================================================
1763 void asm_goto_epilogue( context_t* ctx, atom_t source )
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 }
1775 
1776 //===================================================
1795 //===================================================
1796 int asm_test_prologue( context_t* ctx, int criteria )
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 }
1803 
1804 //===================================================
1831 //===================================================
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 }
1854 
1855 
1856 //===================================================
1881 //===================================================
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 }
1905 
1906 
1907 
1908 
1909 //===================================================
1956 //===================================================
1957 int asm_for_prologue( context_t* ctx, atom_t step_var, atom_t source, int* branch2 )
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 }
1985 
1986 //===================================================
2018 //===================================================
2019 //void rt_for_debug ( int replefts, int repcount, atom_t data )
2020 //{
2021 // printf("atom=");dump_atom(data,1);
2022 // printf("repcount=%d/%d replefts=%d/%d\n",repcount,REPCOUNT(CAR(data)),replefts,REPLIMIT(CAR(data)));
2023 //}
2024 
2025 void asm_for_epilogue( context_t* ctx, int branch, int branch2 )
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 }
2053 
2054 
2055 
2056 //===================================================
2102 //===================================================
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 }
2191 
2192 
2193 
2194 
2195 //===================================================
2213 //===================================================
2214 void asm_internal_function( context_t* ctx, int static_link, atom_t func )
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 }
2278 
2279 
2280 
2281 
2282 
2283 //===================================================
2293 //===================================================
2294 void asm_int_3( context_t* ctx )
2295 {
2296  INT_3;
2297 }
2298 
2299 
2300 
2301 //===================================================
2311 //===================================================
2312 void asm_nop( context_t* ctx )
2313 {
2314  NOP;
2315 }

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