diff options
Diffstat (limited to 'cginstructions.c')
-rw-r--r-- | cginstructions.c | 3821 |
1 files changed, 3821 insertions, 0 deletions
diff --git a/cginstructions.c b/cginstructions.c new file mode 100644 index 0000000..b8c1520 --- /dev/null +++ b/cginstructions.c @@ -0,0 +1,3821 @@ +/* + File: cginstructions.c + Author: John van Groningen + At: University of Nijmegen +*/ + +#include <stdio.h> +#include <string.h> + +#include "cgport.h" + +#ifdef THINK_C +# define SMALL_LAZY_DESCRIPTORS 1 +#else +# define SMALL_LAZY_DESCRIPTORS 0 +#endif + +#include "cg.h" +#include "cgconst.h" +#include "cgrconst.h" +#include "cgtypes.h" +#include "cgcode.h" +#include "cgcodep.h" +#include "cgstack.h" +#include "cglin.h" +#include "cginstructions.h" +#ifdef G_POWER +# include "cgpas.h" +# include "cgpwas.h" +#else +# ifdef I486 +# include "cgias.h" +# include "cgiwas.h" +# else +# ifdef SOLARIS +# include "cgswas.h" +# else +# include "cgas.h" +# include "cgwas.h" +# endif +# endif +#endif +#if defined (M68000) && !defined (SUN) +# define GEN_MAC_OBJ +#endif +#ifndef sparc +# define GEN_OBJ +#endif + +#define LTEXT 0 +#define LDATA 1 + +extern ULONG *offered_vector; +extern int offered_a_stack_size; +extern int offered_b_stack_size; + +extern LABEL *enter_label (char *label_name,int label_flags); +extern LABEL *new_local_label (int label_flags); + +extern LABEL * system_sp_label,*new_int_reducer_label,*channelP_label,*stop_reducer_label, + *send_request_label,*send_graph_label,*string_to_string_node_label; + +#if defined (I486) || defined (G_POWER) +LABEL *saved_heap_p_label,*saved_a_stack_p_label; +#endif +#ifdef MACH_O +LABEL *dyld_stub_binding_helper_p_label; +#endif + +extern struct basic_block *last_block; + +extern ULONG e_vector[],i_vector[],i_i_vector[],i_i_i_vector[],r_vector[]; +extern int reachable; + +extern int line_number; /* from cginput.c */ + +#define HIGH_LOW_FIRST_REAL_IN_RECORD +#define RESERVE_NEW_REDUCER + +LABEL *realloc_0_label,*realloc_1_label,*realloc_2_label,*realloc_3_label, + *schedule_0_label,*schedule_1_label,*schedule_2_label,*schedule_3_label, + *schedule_eval_label,*stack_overflow_label; + +#ifdef I486 +LABEL *end_a_stack_label,*end_b_stack_label; +#endif + +#pragma segment Code20 + +INSTRUCTION_GRAPH g_new_node (int instruction_code,int arity,int arg_size) +{ + INSTRUCTION_GRAPH instruction; + + instruction=(struct instruction_node*)allocate_memory_from_heap (sizeof (struct instruction_node)+arg_size); + + instruction->instruction_code=instruction_code; + instruction->inode_arity=arity; + instruction->node_count=0; + instruction->node_mark=0; + instruction->instruction_d_min_a_cost=0; + instruction->order_mode=0; + + return instruction; +} + +INSTRUCTION_GRAPH g_instruction_1 (int instruction_code,INSTRUCTION_GRAPH graph_1) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (instruction_code,1,sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].p=graph_1; + + return instruction; +} + +INSTRUCTION_GRAPH g_instruction_2 (int instruction_code,INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (instruction_code,2,2*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].p=graph_1; + instruction->instruction_parameters[1].p=graph_2; + + return instruction; +} + +INSTRUCTION_GRAPH g_instruction_2_0 (int instruction_code,INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (instruction_code,3,3*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].p=graph_1; + instruction->instruction_parameters[1].p=graph_2; + instruction->instruction_parameters[2].p=NULL; + + return instruction; +} + +INSTRUCTION_GRAPH g_test_o (INSTRUCTION_GRAPH graph_1) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GTEST_O,1,sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].p=graph_1; + + graph_1->instruction_parameters[2].p=instruction; + + return instruction; +} + +INSTRUCTION_GRAPH g_allocate (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2,int n) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GALLOCATE,2+n,(2+n)*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].p=graph_1; + instruction->instruction_parameters[1].p=graph_2; + + graph_2->instruction_d_min_a_cost+=1; + + return instruction; +} + +static INSTRUCTION_GRAPH g_before0 (INSTRUCTION_GRAPH graph_1,int n) +{ + INSTRUCTION_GRAPH instruction; + int argument_number; + + instruction=g_new_node (GBEFORE0,n+1,(n+1)*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].p=graph_1; + + for (argument_number=0; argument_number<n; ++argument_number) + instruction->instruction_parameters[1+argument_number].p=NULL; + + return instruction; +} + +INSTRUCTION_GRAPH g_copy (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GCOPY,2,2*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].p=graph_1; + instruction->instruction_parameters[1].p=graph_2; + + return instruction; +} + +INSTRUCTION_GRAPH g_create_1 (INSTRUCTION_GRAPH graph_1) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GCREATE,1,sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].p=graph_1; + + return instruction; +} + +INSTRUCTION_GRAPH g_create_2 (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GCREATE,2,2*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].p=graph_1; + instruction->instruction_parameters[1].p=graph_2; + + return instruction; +} + +INSTRUCTION_GRAPH g_create_3 (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2,INSTRUCTION_GRAPH graph_3) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GCREATE,3,3*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].p=graph_1; + instruction->instruction_parameters[1].p=graph_2; + instruction->instruction_parameters[2].p=graph_3; + + return instruction; +} + +INSTRUCTION_GRAPH g_create_m (int arity) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GCREATE,arity,arity*sizeof (union instruction_parameter)); + + return instruction; +} + +INSTRUCTION_GRAPH g_create_r (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GCREATE_R,2,2*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].p=graph_1; + instruction->instruction_parameters[1].p=graph_2; + + return instruction; +} + +INSTRUCTION_GRAPH g_exit_if (LABEL *label,INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2) +{ + INSTRUCTION_GRAPH exit_if_graph; + + exit_if_graph=g_new_node (GEXIT_IF,3,3*sizeof (union instruction_parameter)); + + exit_if_graph->instruction_parameters[0].l=label; + exit_if_graph->instruction_parameters[1].p=graph_1; + exit_if_graph->instruction_parameters[2].p=graph_2; + + return exit_if_graph; +} + +INSTRUCTION_GRAPH g_fill_2 (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GFILL,2,2*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].p=graph_1; + instruction->instruction_parameters[1].p=graph_2; + + graph_1->instruction_d_min_a_cost+=1; + + if (graph_1->instruction_code==GBEFORE0) + graph_1->instruction_code=GBEFORE; + else if (graph_1->instruction_code==GCREATE && graph_1->inode_arity>0) + graph_1->instruction_parameters[0].p=NULL; + + return instruction; +} + +INSTRUCTION_GRAPH g_fill_3 (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2,INSTRUCTION_GRAPH graph_3) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GFILL,3,3*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].p=graph_1; + instruction->instruction_parameters[1].p=graph_2; + instruction->instruction_parameters[2].p=graph_3; + + graph_1->instruction_d_min_a_cost+=1; + + if (graph_1->instruction_code==GBEFORE0) + graph_1->instruction_code=GBEFORE; + else if (graph_1->instruction_code==GCREATE){ + int arity; + + arity=graph_1->inode_arity; + if (arity>2) + arity=2; + + while (arity>0) + graph_1->instruction_parameters[--arity].p=NULL; + } + + return instruction; +} + +INSTRUCTION_GRAPH g_fill_4 (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2,INSTRUCTION_GRAPH graph_3, + INSTRUCTION_GRAPH graph_4) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GFILL,4,4*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].p=graph_1; + instruction->instruction_parameters[1].p=graph_2; + instruction->instruction_parameters[2].p=graph_3; + instruction->instruction_parameters[3].p=graph_4; + + graph_1->instruction_d_min_a_cost+=1; + + if (graph_1->instruction_code==GBEFORE0) + graph_1->instruction_code=GBEFORE; + else if (graph_1->instruction_code==GCREATE){ + int arity; + + arity=graph_1->inode_arity; + if (arity>3) + arity=3; + + while (arity>0) + graph_1->instruction_parameters[--arity].p=NULL; + } + + return instruction; +} + +INSTRUCTION_GRAPH g_fill_m (INSTRUCTION_GRAPH graph_1,int arity) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GFILL,arity+1,(arity+1)*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].p=graph_1; + + graph_1->instruction_d_min_a_cost+=1; + + if (graph_1->instruction_code==GBEFORE0) + graph_1->instruction_code=GBEFORE; + else if (graph_1->instruction_code==GCREATE){ + int arity; + + arity=graph_1->inode_arity; + if (arity>2) + arity=2; + + while (arity>0) + graph_1->instruction_parameters[--arity].p=NULL; + } + + return instruction; +} + +INSTRUCTION_GRAPH g_fill_r (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2,INSTRUCTION_GRAPH graph_3) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GFILL_R,3,3*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].p=graph_1; + instruction->instruction_parameters[1].p=graph_2; + instruction->instruction_parameters[2].p=graph_3; + + graph_1->instruction_d_min_a_cost+=1; + + if (graph_1->instruction_code==GBEFORE0) + graph_1->instruction_code=GBEFORE; + else if (graph_1->instruction_code==GCREATE){ + int arity=graph_1->inode_arity; + if (arity>3) + arity=3; + + while (arity>0) + graph_1->instruction_parameters[--arity].p=NULL; + } + + return instruction; +} + +INSTRUCTION_GRAPH g_fjoin (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2) +{ + if (graph_1->instruction_code==GFHIGH && graph_2->instruction_code==GFLOW + && graph_1->instruction_parameters[0].p==graph_2->instruction_parameters[0].p) + return graph_1->instruction_parameters[0].p; + + if (graph_1->instruction_code==GLOAD && graph_2->instruction_code==GLOAD + && graph_1->instruction_parameters[1].i==graph_2->instruction_parameters[1].i + && graph_1->instruction_parameters[0].i+4==graph_2->instruction_parameters[0].i) + { + INSTRUCTION_GRAPH fload_graph; + + fload_graph=g_fload (graph_1->instruction_parameters[0].i,graph_1->instruction_parameters[1].i); + + graph_1->instruction_code=GFHIGH; + graph_2->instruction_code=GFLOW; + graph_1->instruction_parameters[0].p=fload_graph; + graph_2->instruction_parameters[0].p=fload_graph; +#ifdef g_fhighlow + graph_1->instruction_parameters[1].p=graph_2; + graph_2->instruction_parameters[1].p=graph_1; +#endif + return fload_graph; + } + + if (graph_1->instruction_code==GLOAD_ID && graph_2->instruction_code==GLOAD_ID +# ifdef HIGH_LOW_FIRST_REAL_IN_RECORD + ) + if (!(graph_1->instruction_parameters[1].i==graph_2->instruction_parameters[1].i + && graph_1->instruction_parameters[0].i+4==graph_2->instruction_parameters[0].i)) + { + INSTRUCTION_GRAPH join_graph,load_id_graph_1,load_id_graph_2; + + load_id_graph_1=g_load_id (graph_1->instruction_parameters[0].i,graph_1->instruction_parameters[1].p); + load_id_graph_2=g_load_id (graph_2->instruction_parameters[0].i,graph_2->instruction_parameters[1].p); + + join_graph=g_instruction_2 (GFJOIN,load_id_graph_1,load_id_graph_2); + + graph_1->instruction_code=GFHIGH; + graph_1->instruction_parameters[0].p=join_graph; + graph_1->instruction_parameters[1].p=graph_2; + + graph_2->instruction_code=GFLOW; + graph_2->instruction_parameters[0].p=join_graph; + graph_2->instruction_parameters[1].p=graph_1; + + return join_graph; + } else +# else + && graph_1->instruction_parameters[1].i==graph_2->instruction_parameters[1].i + && graph_1->instruction_parameters[0].i+4==graph_2->instruction_parameters[0].i) +# endif + { + INSTRUCTION_GRAPH fload_graph; + + fload_graph= + g_fload_id (graph_1->instruction_parameters[0].i,graph_1->instruction_parameters[1].p); + + graph_1->instruction_code=GFHIGH; + graph_1->instruction_parameters[0].p=fload_graph; + graph_1->instruction_parameters[1].p=graph_2; + + graph_2->instruction_code=GFLOW; + graph_2->instruction_parameters[0].p=fload_graph; + graph_2->instruction_parameters[1].p=graph_1; + + return fload_graph; + } + + if (graph_1->instruction_code==GMOVEMI && graph_2->instruction_code==GMOVEMI + && graph_1->instruction_parameters[0].p==graph_2->instruction_parameters[0].p + && graph_1->inode_arity+1==graph_2->inode_arity) + { + INSTRUCTION_GRAPH fmovemi_graph,movem_graph; + int number; + + movem_graph=graph_1->instruction_parameters[0].p; + number=graph_1->inode_arity; + + fmovemi_graph=g_new_node (GFMOVEMI,number,2*sizeof (union instruction_parameter)); + + fmovemi_graph->instruction_parameters[0].p=movem_graph; + fmovemi_graph->instruction_parameters[1].i=0; + + movem_graph->instruction_parameters[2+number].p=fmovemi_graph; + movem_graph->instruction_parameters[2+number+1].p=NULL; + + graph_1->instruction_code=GFHIGH; + graph_1->instruction_parameters[0].p=fmovemi_graph; + graph_1->instruction_parameters[1].p=graph_2; + + graph_2->instruction_code=GFLOW; + graph_2->instruction_parameters[0].p=fmovemi_graph; + graph_2->instruction_parameters[1].p=graph_1; + + return fmovemi_graph; + } + + if (graph_1->instruction_code==GLOAD_X && graph_2->instruction_code==GLOAD_X + && graph_1->instruction_parameters[1].i+(4<<2)==graph_2->instruction_parameters[1].i + && graph_1->instruction_parameters[0].p==graph_2->instruction_parameters[0].p + && graph_1->instruction_parameters[2].p==graph_2->instruction_parameters[2].p + && graph_1->instruction_parameters[3].p==graph_2) + { + INSTRUCTION_GRAPH fload_graph,*previous_loadx; + + previous_loadx=&load_indexed_list; + + /* added 25-10-2001 */ + while (*previous_loadx!=NULL && *previous_loadx!=graph_1) + /* while (*previous_loadx!=graph_1) */ + previous_loadx=&(*previous_loadx)->instruction_parameters[3].p; + + fload_graph=g_new_node (GFLOAD_X,0,4*sizeof (union instruction_parameter)); + + fload_graph->instruction_parameters[0].p=graph_1->instruction_parameters[0].p; + fload_graph->instruction_parameters[1].i=graph_1->instruction_parameters[1].i; + fload_graph->instruction_parameters[2].p=graph_1->instruction_parameters[2].p; + + fload_graph->instruction_parameters[3].p=graph_2->instruction_parameters[3].p; + + /* added 25-10-2001 */ + if (*previous_loadx!=NULL) + /* */ + *previous_loadx=fload_graph; + + fload_graph->instruction_d_min_a_cost+=1; + + graph_1->instruction_code=GFHIGH; + graph_1->instruction_parameters[0].p=fload_graph; + graph_1->instruction_parameters[1].p=graph_2; + graph_1->instruction_parameters[3].p=fload_graph; + + graph_2->instruction_code=GFLOW; + graph_2->instruction_parameters[0].p=fload_graph; + graph_2->instruction_parameters[1].p=graph_1; + graph_2->instruction_parameters[3].p=fload_graph; + + return fload_graph; + } + + return g_instruction_2 (GFJOIN,graph_1,graph_2); +} + +INSTRUCTION_GRAPH g_fload (int offset,int stack) +{ + register INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GFLOAD,0,2*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].i=offset; + instruction->instruction_parameters[1].i=stack; + + return instruction; +} + +INSTRUCTION_GRAPH g_fload_i (DOUBLE v) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GFLOAD_I,0,sizeof (DOUBLE)); + + *(DOUBLE*)&instruction->instruction_parameters[0]=v; + + return instruction; +} + +INSTRUCTION_GRAPH g_fload_id (int offset,INSTRUCTION_GRAPH graph_1) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GFLOAD_ID,0,2*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].i=offset; + instruction->instruction_parameters[1].p=graph_1; + + graph_1->instruction_d_min_a_cost+=1; + + return instruction; +} + +INSTRUCTION_GRAPH g_fload_x + (INSTRUCTION_GRAPH graph_1,int offset,int shift,INSTRUCTION_GRAPH graph_2) +{ + register INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GFLOAD_X,0,4*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].p=graph_1; + instruction->instruction_parameters[1].i=(offset<<2) | shift; + instruction->instruction_parameters[2].p=graph_2; + instruction->instruction_parameters[3].p=load_indexed_list; + + graph_1->instruction_d_min_a_cost+=1; + + load_indexed_list=instruction; + + return instruction; +} + +INSTRUCTION_GRAPH g_fstore (int offset,int reg_1,INSTRUCTION_GRAPH graph_1, + INSTRUCTION_GRAPH graph_2,INSTRUCTION_GRAPH graph_3) +{ + register INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GFSTORE,0,5*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].i=offset; + instruction->instruction_parameters[1].i=reg_1; + instruction->instruction_parameters[2].p=graph_1; + + if (graph_2 && (graph_2->instruction_code==GFLOW || graph_2->instruction_code==GFHIGH)) + instruction->instruction_parameters[3].p=graph_2->instruction_parameters[0].p; + else + instruction->instruction_parameters[3].p=graph_2; + + if (graph_3 && (graph_3->instruction_code==GFLOW || graph_3->instruction_code==GFHIGH)) + instruction->instruction_parameters[4].p=graph_3->instruction_parameters[0].p; + else + instruction->instruction_parameters[4].p=graph_3; + + return instruction; +} + +INSTRUCTION_GRAPH g_fstore_r (int reg_1,INSTRUCTION_GRAPH graph_1) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GFSTORE_R,0,2*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].i=reg_1; + instruction->instruction_parameters[1].p=graph_1; + + return instruction; +} + +INSTRUCTION_GRAPH g_lea (LABEL *label) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GLEA,0,sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].l=label; + + return instruction; +} + +INSTRUCTION_GRAPH g_lea_i (LABEL *label,int offset) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GLEA,1,2*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].l=label; + instruction->instruction_parameters[1].i=offset; + + return instruction; +} + +INSTRUCTION_GRAPH g_load (int offset,int stack) +{ + register INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GLOAD,0,2*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].i=offset; + instruction->instruction_parameters[1].i=stack; + + return instruction; +} + +INSTRUCTION_GRAPH g_load_i (LONG value) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GLOAD_I,0,sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].i=value; + + return instruction; +} + +INSTRUCTION_GRAPH g_load_id (int offset,INSTRUCTION_GRAPH graph_1) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GLOAD_ID,0,2*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].i=offset; + instruction->instruction_parameters[1].p=graph_1; + + graph_1->instruction_d_min_a_cost+=1; + + return instruction; +} + +INSTRUCTION_GRAPH g_load_b_x (INSTRUCTION_GRAPH graph_1,int offset,int sign_extend,INSTRUCTION_GRAPH graph_2) +{ + register INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GLOAD_B_X,0,4*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].p=graph_1; + instruction->instruction_parameters[1].i=(offset<<2) | sign_extend; + instruction->instruction_parameters[2].p=graph_2; + instruction->instruction_parameters[3].p=load_indexed_list; + + graph_1->instruction_d_min_a_cost+=1; + + load_indexed_list=instruction; + + return instruction; +} + +INSTRUCTION_GRAPH g_load_x (INSTRUCTION_GRAPH graph_1,int offset,int shift,INSTRUCTION_GRAPH graph_2) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GLOAD_X,0,4*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].p=graph_1; + instruction->instruction_parameters[1].i=(offset<<2) | shift; + instruction->instruction_parameters[2].p=graph_2; + instruction->instruction_parameters[3].p=load_indexed_list; + + graph_1->instruction_d_min_a_cost+=1; + + load_indexed_list=instruction; + + return instruction; +} + +INSTRUCTION_GRAPH g_load_b_id (int offset,INSTRUCTION_GRAPH graph_1) +{ + register INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GLOAD_B_ID,0,2*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].i=offset; + instruction->instruction_parameters[1].p=graph_1; + + graph_1->instruction_d_min_a_cost+=1; + + return instruction; +} + +INSTRUCTION_GRAPH g_load_des_i (LABEL *descriptor_label,int arity) +{ + register INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GLOAD_DES_I,0,2*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].l=descriptor_label; +#ifdef I486 + instruction->instruction_parameters[1].i=(arity<<3)+2; +#else + instruction->instruction_parameters[1].i=arity; +#endif + + return instruction; +} + +INSTRUCTION_GRAPH g_load_des_id (int offset,INSTRUCTION_GRAPH graph_1) +{ + register INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GLOAD_DES_ID,0,2*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].i=offset; + instruction->instruction_parameters[1].p=graph_1; + + graph_1->instruction_d_min_a_cost+=1; + + return instruction; +} + +INSTRUCTION_GRAPH g_movem (int offset,INSTRUCTION_GRAPH graph_1,int n) +{ + INSTRUCTION_GRAPH instruction; + int argument_number; + + instruction=g_new_node (GMOVEM,n,(2+n)*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].i=offset; + instruction->instruction_parameters[1].p=graph_1; + + for (argument_number=0; argument_number<n; ++argument_number) + instruction->instruction_parameters[2+argument_number].p=NULL; + + return instruction; +} + +INSTRUCTION_GRAPH g_movemi (int number,INSTRUCTION_GRAPH movem_graph) +{ + register INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GMOVEMI,number,2*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].p=movem_graph; + instruction->instruction_parameters[1].i=0; + + movem_graph->instruction_parameters[2+number].p=instruction; + + return instruction; +} + +INSTRUCTION_GRAPH g_fregister (int float_reg) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GFREGISTER,0,sizeof (union instruction_parameter)); + + if ((unsigned)float_reg<(unsigned)N_FLOAT_PARAMETER_REGISTERS) + global_block.block_graph_f_register_parameter_node[float_reg]=instruction; + + instruction->instruction_parameters[0].i=float_reg; + + return instruction; +} + +INSTRUCTION_GRAPH g_fstore_x (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2,int offset,int shift,INSTRUCTION_GRAPH graph_3) +{ + register INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GFSTORE_X,0,5*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].p=graph_1; + instruction->instruction_parameters[1].p=graph_2; + instruction->instruction_parameters[2].i=(offset<<2) | shift; + instruction->instruction_parameters[3].p=graph_3; + instruction->instruction_parameters[4].p=load_indexed_list; + + graph_2->instruction_d_min_a_cost+=1; + + return instruction; +} + +INSTRUCTION_GRAPH g_g_register (int reg) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GGREGISTER,0,sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].i=reg; + + return instruction; +} + +INSTRUCTION_GRAPH g_register (int reg) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GREGISTER,0,sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].i=reg; + + if ((unsigned)a_reg_num (reg)<(unsigned)N_ADDRESS_PARAMETER_REGISTERS) + global_block.block_graph_a_register_parameter_node[a_reg_num (reg)]=instruction; + + if ((unsigned)d_reg_num (reg)<(unsigned)N_DATA_PARAMETER_REGISTERS) + global_block.block_graph_d_register_parameter_node[d_reg_num (reg)]=instruction; + + return instruction; +} + +INSTRUCTION_GRAPH g_store (int offset,int reg_1,INSTRUCTION_GRAPH graph_1, + INSTRUCTION_GRAPH graph_2) +{ + register INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GSTORE,0,4*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].i=offset; + instruction->instruction_parameters[1].i=reg_1; + instruction->instruction_parameters[2].p=graph_1; + + if (graph_2 && (graph_2->instruction_code==GFLOW || graph_2->instruction_code==GFHIGH)) + instruction->instruction_parameters[3].p=graph_2->instruction_parameters[0].p; + else + instruction->instruction_parameters[3].p=graph_2; + + return instruction; +} + +INSTRUCTION_GRAPH g_store_b_x (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2,int offset,INSTRUCTION_GRAPH graph_3) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GSTORE_B_X,0,5*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].p=graph_1; + instruction->instruction_parameters[1].p=graph_2; + instruction->instruction_parameters[2].i=(offset<<2); + instruction->instruction_parameters[3].p=graph_3; + instruction->instruction_parameters[4].p=load_indexed_list; + + graph_2->instruction_d_min_a_cost+=1; + + return instruction; +} + +INSTRUCTION_GRAPH g_store_x (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2,int offset,int shift,INSTRUCTION_GRAPH graph_3) +{ + INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GSTORE_X,0,5*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].p=graph_1; + instruction->instruction_parameters[1].p=graph_2; + instruction->instruction_parameters[2].i=(offset<<2) | shift; + instruction->instruction_parameters[3].p=graph_3; + instruction->instruction_parameters[4].p=load_indexed_list; + + graph_2->instruction_d_min_a_cost+=1; + + return instruction; +} + +INSTRUCTION_GRAPH g_store_r (int reg_1,INSTRUCTION_GRAPH graph_1) +{ + register INSTRUCTION_GRAPH instruction; + + instruction=g_new_node (GSTORE_R,0,2*sizeof (union instruction_parameter)); + + instruction->instruction_parameters[0].i=reg_1; + instruction->instruction_parameters[1].p=graph_1; + + if (graph_1->instruction_code==GMOVEMI) + graph_1->instruction_parameters[1].i=(reg_1<<1)+1; + + return instruction; +} + +LABEL *w_code_string (char *string,int length) +{ + LABEL *string_label; + + string_label=new_local_label (LOCAL_LABEL +#ifdef G_POWER + | DATA_LABEL +#endif + ); + +#ifdef GEN_MAC_OBJ + start_new_module (0); + if (assembly_flag) + w_as_new_module (0); +#endif +#if defined (G_POWER) || defined (_WINDOWS_) + as_new_data_module(); + if (assembly_flag) + w_as_new_data_module(); +#endif + +#ifdef GEN_MAC_OBJ + define_local_label (string_label->label_id,LTEXT); + store_c_string_in_code_section (string,length); +#else +# ifdef GEN_OBJ + define_data_label (string_label); + store_c_string_in_data_section (string,length); +# endif +#endif + + if (assembly_flag) +#ifdef GEN_MAC_OBJ + w_as_c_string_in_code_section (string,length,string_label->label_number); +#else + w_as_labeled_c_string_in_data_section (string,length,string_label->label_number); +#endif + + return string_label; +} + +LABEL *w_code_descriptor_length_and_string (char *string,int length) +{ + LABEL *string_label; + + if (_STRING__label==NULL) + _STRING__label=enter_label ("__STRING__",IMPORT_LABEL | DATA_LABEL); + + string_label=new_local_label (LOCAL_LABEL +#ifdef G_POWER + | DATA_LABEL +#endif + ); + +#ifdef GEN_MAC_OBJ + start_new_module (4); + if (assembly_flag) + w_as_new_module (4); +#endif +#if defined (G_POWER) || defined (_WINDOWS_) + as_new_data_module(); + if (assembly_flag) + w_as_new_data_module(); +#endif + +#ifdef GEN_MAC_OBJ + define_local_label (string_label->label_id,LTEXT); + if (_STRING__label->label_id<0) + _STRING__label->label_id=next_label_id++; + store_descriptor_in_code_section (_STRING__label->label_id); + store_abc_string_in_code_section (string,length); + + if (assembly_flag){ + w_as_define_local_label_in_code_section (string_label->label_number); + w_as_descriptor_in_code_section (_STRING__label->label_name); + w_as_abc_string_in_code_section (string,length); + } +#else +# ifdef GEN_OBJ + define_data_label (string_label); + if (_STRING__label->label_id<0) + _STRING__label->label_id=next_label_id++; + store_descriptor_in_data_section (_STRING__label); + store_abc_string_in_data_section (string,length); +# endif + + if (assembly_flag){ + w_as_define_data_label (string_label->label_number); + w_as_descriptor_in_data_section (_STRING__label->label_name); + w_as_abc_string_in_data_section (string,length); + } +#endif + + return string_label; +} + +LABEL *w_code_length_and_string (char *string,int length) +{ + LABEL *string_label; + + string_label=new_local_label (LOCAL_LABEL +#ifdef G_POWER + | DATA_LABEL +#endif + ); + +#ifdef GEN_MAC_OBJ + start_new_module (0); + if (assembly_flag) + w_as_new_module (0); +#endif +#if defined (G_POWER) || defined (_WINDOWS_) + as_new_data_module(); + if (assembly_flag) + w_as_new_data_module(); +#endif + +#ifdef GEN_MAC_OBJ + define_local_label (string_label->label_id,LTEXT); + store_abc_string_in_code_section (string,length); + + if (assembly_flag){ + w_as_define_local_label_in_code_section (string_label->label_number); + w_as_abc_string_in_code_section (string,length); + } +#else +# ifdef GEN_OBJ + define_data_label (string_label); + store_abc_string_in_data_section (string,length); +# endif + + if (assembly_flag){ + w_as_define_data_label (string_label->label_number); + w_as_abc_string_in_data_section (string,length); + } +#endif + return string_label; +} + +void w_descriptor_string (char *string,int length,int string_code_label_id,LABEL *string_label) +{ +#ifdef GEN_MAC_OBJ + store_descriptor_string_in_code_section (string,length,string_code_label_id,string_label); + + if (assembly_flag) + w_as_descriptor_string_in_code_section (string,length,string_code_label_id,string_label); +#else +# ifdef GEN_OBJ + store_descriptor_string_in_data_section (string,length,string_label); +# endif + + if (assembly_flag) + w_as_descriptor_string_in_data_section (string,length,string_code_label_id,string_label); +#endif +} + +void code_n_string (char string[],int string_length) +{ +} + +void code_fill1_r (char descriptor_name[],int a_size,int b_size,int root_offset,char bits[]) +{ + INSTRUCTION_GRAPH graph_1,graph_2,graph_3,graph_4,graph_5,graph_6; + LABEL *descriptor_label; + + graph_1=s_get_a (root_offset); + + if (bits[0]=='1'){ + descriptor_label=enter_label (descriptor_name,DATA_LABEL); + + if (!parallel_flag && descriptor_label->label_last_lea_block==last_block) + graph_2=descriptor_label->label_last_lea; + else { + graph_2=g_load_des_i (descriptor_label,0); + + if (!parallel_flag ){ + descriptor_label->label_last_lea=graph_2; + descriptor_label->label_last_lea_block=last_block; + } + } + } else + graph_2=NULL; + + switch (a_size+b_size){ + case 0: + graph_4=g_fill_2 (graph_1,graph_2); + break; + case 1: + if (bits[1]=='0') + graph_5=NULL; + else + if (a_size!=0){ + graph_5=s_pop_a(); + --root_offset; + } else + graph_5=s_pop_b(); + graph_4=g_fill_3 (graph_1,graph_2,graph_5); + break; + case 2: + switch (b_size){ + case 0: + if (bits[1]=='0') + graph_5=NULL; + else { + graph_5=s_pop_a(); + --root_offset; + } + if (bits[2]=='0') + graph_6=NULL; + else { + graph_6=s_pop_a(); + --root_offset; + } + break; + case 1: + if (bits[1]=='0') + graph_5=NULL; + else { + graph_5=s_pop_a(); + --root_offset; + } + if (bits[2]=='0') + graph_6=NULL; + else + graph_6=s_pop_b(); + break; + default: + if (bits[1]=='0') + graph_5=NULL; + else + graph_5=s_pop_b(); + if (bits[2]=='0') + graph_6=NULL; + else + graph_6=s_pop_b(); + } + graph_4=g_fill_4 (graph_1,graph_2,graph_5,graph_6); + break; + default: + { + union instruction_parameter *parameter; + int a_n,b_n; + + a_n=0; + b_n=0; + + if (a_n<a_size){ + graph_5=s_pop_a(); + --root_offset; + ++a_n; + } else { + graph_5=s_pop_b(); + ++b_n; + } + + graph_3=g_create_m (a_size+b_size-1); + + parameter=graph_3->instruction_parameters; + + while (a_n<a_size){ + if (bits[a_n+1]=='0') + parameter->p=NULL; + else { + parameter->p=s_pop_a(); + --root_offset; + } + ++parameter; + ++a_n; + } + + while (b_n<b_size){ + if (bits[b_n+a_size+1]=='0') + parameter->p=NULL; + else + parameter->p=s_pop_b(); + ++parameter; + ++b_n; + } + + graph_4=g_fill_4 (graph_1,graph_2,graph_5,graph_3); + } + } + + s_put_a (root_offset,graph_4); +} + +#define g_keep(g1,g2) g_instruction_2(GKEEP,(g1),(g2)) + +void code_fill2_r (char descriptor_name[],int a_size,int b_size,int root_offset,char bits[]) +{ + INSTRUCTION_GRAPH graph_1,graph_2,graph_3,graph_4,graph_5; + LABEL *descriptor_label; + union instruction_parameter *parameter; + int a_n,b_n; + + graph_1=s_get_a (root_offset); + if (graph_1->instruction_code==GBEFORE0) + graph_1->instruction_code=GBEFORE; + + if (bits[0]=='1'){ + descriptor_label=enter_label (descriptor_name,DATA_LABEL); + + if (!parallel_flag && descriptor_label->label_last_lea_block==last_block) + graph_2=descriptor_label->label_last_lea; + else { + graph_2=g_load_des_i (descriptor_label,0); + + if (!parallel_flag ){ + descriptor_label->label_last_lea=graph_2; + descriptor_label->label_last_lea_block=last_block; + } + } + } else + graph_2=NULL; + + a_n=0; + b_n=0; + + if (a_n<a_size){ + if (bits[a_n+1]=='0') + graph_5=NULL; + else { + graph_5=s_pop_a(); + --root_offset; + } + ++a_n; + } else { + if (bits[b_n+a_size+1]=='0') + graph_5=NULL; + else + graph_5=s_pop_b(); + ++b_n; + } + + graph_3=g_fill_m (g_load_id (8,graph_1),a_size+b_size-1); + + parameter=&graph_3->instruction_parameters[1]; + + while (a_n<a_size){ + if (bits[a_n+1]=='0') + parameter->p=NULL; + else { + parameter->p=s_pop_a(); + --root_offset; + } + ++parameter; + ++a_n; + } + + while (b_n<b_size){ + if (bits[b_n+a_size+1]=='0') + parameter->p=NULL; + else + parameter->p=s_pop_b(); + ++parameter; + ++b_n; + } + + graph_4=g_fill_3 (g_keep (graph_3,graph_1),graph_2,graph_5); + + s_put_a (root_offset,graph_4); +} + +extern LABEL *cycle_in_spine_label,*reserve_label; + +void code_fill3_r (char descriptor_name[],int a_size,int b_size,int root_offset,char bits[]) +{ + INSTRUCTION_GRAPH graph_0,graph_1,graph_2,graph_3,graph_4,graph_5,graph_6; + LABEL *descriptor_label; + union instruction_parameter *parameter; + int a_n,b_n; + + graph_0=s_pop_a(); + if (graph_0->instruction_code==GBEFORE0) + graph_0->instruction_code=GBEFORE; + --root_offset; + +#if !(defined (sparc) || defined (G_POWER)) + if (!parallel_flag){ + if (cycle_in_spine_label==NULL){ + cycle_in_spine_label=enter_label ("__cycle__in__spine",IMPORT_LABEL | NODE_ENTRY_LABEL); + cycle_in_spine_label->label_arity=0; + cycle_in_spine_label->label_descriptor=EMPTY_label; + } + graph_6=g_lea (cycle_in_spine_label); + } else { + if (reserve_label==NULL){ + reserve_label=enter_label ("__reserve",IMPORT_LABEL | NODE_ENTRY_LABEL); + reserve_label->label_arity=0; + reserve_label->label_descriptor=EMPTY_label; + } + graph_6=g_lea (reserve_label); + } +#else + graph_6=g_g_register (RESERVE_CODE_REGISTER); +#endif + graph_0=g_fill_2 (graph_0,graph_6); + + graph_1=s_get_a (root_offset); + if (graph_1->instruction_code==GBEFORE0) + graph_1->instruction_code=GBEFORE; + + descriptor_label=enter_label (descriptor_name,DATA_LABEL); + + if (!parallel_flag && descriptor_label->label_last_lea_block==last_block) + graph_2=descriptor_label->label_last_lea; + else { + graph_2=g_load_des_i (descriptor_label,0); + + if (!parallel_flag ){ + descriptor_label->label_last_lea=graph_2; + descriptor_label->label_last_lea_block=last_block; + } + } + + a_n=0; + b_n=0; + + if (bits[0]=='0'){ + graph_5=g_load_id (4,graph_0); + if (a_n<a_size) + ++a_n; + else + ++b_n; + } else { + if (a_n<a_size){ + graph_5=s_pop_a(); + --root_offset; + ++a_n; + } else { + graph_5=s_pop_b(); + ++b_n; + } + } + + graph_0=g_load_id (8,graph_0); + + graph_3=g_fill_m (graph_0,a_size+b_size-1); + + parameter=&graph_3->instruction_parameters[1]; + + while (a_n<a_size){ + if (bits[a_n]=='0') + parameter->p=NULL; + else { + parameter->p=s_pop_a(); + --root_offset; + } + ++parameter; + ++a_n; + } + + while (b_n<b_size){ + if (bits[b_n+a_size]=='0') + parameter->p=NULL; + else + parameter->p=s_pop_b(); + ++parameter; + ++b_n; + } + + graph_4=g_fill_4 (graph_1,graph_2,graph_5,graph_3); + + s_put_a (root_offset,graph_4); +} + +#define ARGUMENTS_OFFSET 4 + +void code_push_args_u (int a_offset,int arity,int n_arguments) +{ + INSTRUCTION_GRAPH graph_1,graph_2,graph_3,graph_5,*graph_p; + + graph_1=s_get_a (a_offset); + + graph_5=g_before0 (graph_1,n_arguments); + graph_p=&graph_5->instruction_parameters[1+n_arguments].p; + + s_put_a (a_offset,graph_5); + + if (n_arguments>0){ + graph_2=g_load_id (ARGUMENTS_OFFSET-NODE_POINTER_OFFSET,graph_1); + + if (n_arguments!=1) + if (n_arguments==2 && arity==2){ + graph_3=g_load_id (8-NODE_POINTER_OFFSET,graph_1); + *--graph_p=graph_3; + s_push_a (graph_3); + } else { + INSTRUCTION_GRAPH graph_4; + + graph_3=g_load_id (8-NODE_POINTER_OFFSET,graph_1); + --n_arguments; + + if (n_arguments==1){ + graph_4=g_load_id (0-NODE_POINTER_OFFSET,graph_3); + *--graph_p=graph_4; + s_push_a (graph_4); + } else { +#ifndef I486 + if (n_arguments>=8){ +#endif + while (n_arguments!=0){ + INSTRUCTION_GRAPH graph_5; + + --n_arguments; + + graph_5=g_load_id ((n_arguments<<2)-NODE_POINTER_OFFSET,graph_3); + *--graph_p=graph_5; + s_push_a (graph_5); + } +#ifndef I486 + } else { + graph_4=g_movem (0-NODE_POINTER_OFFSET,graph_3,n_arguments); + while (n_arguments!=0){ + INSTRUCTION_GRAPH graph_5; + + --n_arguments; + + graph_5=g_movemi (n_arguments,graph_4); + *--graph_p=graph_5; + s_push_a (graph_5); + } + } +#endif + } + } + + *--graph_p=graph_2; + s_push_a (graph_2); + } +} + +void code_push_r_args_u (int a_offset,int a_size,int b_size) +{ + INSTRUCTION_GRAPH graph_1,graph_2,graph_3,graph_5,graph_6,*graph_p; + + graph_1=s_get_a (a_offset); + + graph_6=g_before0 (graph_1,a_size+b_size); + graph_p=&graph_6->instruction_parameters[1+a_size+b_size].p; + + s_put_a (a_offset,graph_6); + + switch (a_size+b_size){ + case 0: + return; + case 1: + graph_2=g_load_id (ARGUMENTS_OFFSET,graph_1); + *--graph_p=graph_2; + if (a_size!=0) + s_push_a (graph_2); + else + s_push_b (graph_2); + return; + case 2: + graph_2=g_load_id (ARGUMENTS_OFFSET,graph_1); + graph_3=g_load_id (8,graph_1); + *--graph_p=graph_3; + *--graph_p=graph_2; + switch (b_size){ + case 0: + s_push_a (graph_3); + s_push_a (graph_2); + break; + case 1: + s_push_a (graph_2); + s_push_b (graph_3); + break; + default: + s_push_b (graph_3); + s_push_b (graph_2); + } + return; + default: + graph_2=g_load_id (ARGUMENTS_OFFSET,graph_1); + graph_3=g_load_id (8,graph_1); + +#ifdef M68000 + if (a_size+b_size-1>=8){ +#endif + b_size+=a_size; + + while (b_size>a_size && b_size>1){ + --b_size; + graph_5=g_load_id ((b_size-1)<<2,graph_3); + *--graph_p=graph_5; + s_push_b (graph_5); + } + + while (a_size>1){ + --a_size; + graph_5=g_load_id ((a_size-1)<<2,graph_3); + *--graph_p=graph_5; + s_push_a (graph_5); + } +#ifdef M68000 + } else { + INSTRUCTION_GRAPH graph_4; + + graph_4=g_movem (0,graph_3,a_size+b_size-1); + + b_size+=a_size; + + while (b_size>a_size && b_size>1){ + --b_size; + graph_5=g_movemi (b_size-1,graph_4); + *--graph_p=graph_5; + s_push_b (graph_5); + } + + while (a_size>1){ + --a_size; + graph_5=g_movemi (a_size-1,graph_4); + *--graph_p=graph_5; + s_push_a (graph_5); + } + } +#endif + *--graph_p=graph_2; + if (a_size>0) + s_push_a (graph_2); + else + s_push_b (graph_2); + return; + } +} + +void code_push_r_arg_u (int a_offset,int a_size,int b_size,int a_arg_offset,int a_arg_size,int b_arg_offset,int b_arg_size) +{ + INSTRUCTION_GRAPH graph_1,graph_2,graph_3,graph_5,graph_6,*graph_p; + + graph_1=s_get_a (a_offset); + + if (graph_1->instruction_code==GBEFORE0 && graph_1->inode_arity==a_size+b_size+1) + graph_p=&graph_1->instruction_parameters[1].p; + else { + graph_6=g_before0 (graph_1,a_size+b_size); + graph_p=&graph_6->instruction_parameters[1+a_size+b_size].p; + + s_put_a (a_offset,graph_6); + + switch (a_size+b_size){ + case 0: + break; + case 1: + graph_2=g_load_id (ARGUMENTS_OFFSET,graph_1); + *--graph_p=graph_2; + break; + case 2: + graph_2=g_load_id (ARGUMENTS_OFFSET,graph_1); + graph_3=g_load_id (8,graph_1); + *--graph_p=graph_3; + *--graph_p=graph_2; + break; + default: + { + int ab_size; + + graph_2=g_load_id (ARGUMENTS_OFFSET,graph_1); + graph_3=g_load_id (8,graph_1); + + ab_size=a_size+b_size-1; +#ifdef M68000 + if (ab_size>=8){ +#endif + while (ab_size>0){ + --ab_size; + graph_5=g_load_id (ab_size<<2,graph_3); + *--graph_p=graph_5; + } +#ifdef M68000 + } else { + INSTRUCTION_GRAPH graph_4; + + graph_4=g_movem (0,graph_3,ab_size); + + while (ab_size>1){ + --ab_size; + graph_5=g_movemi (ab_size,graph_4); + *--graph_p=graph_5; + } + } +#endif + *--graph_p=graph_2; + break; + } + } + } + + while (a_arg_size>0){ + --a_arg_size; + s_push_a (graph_p[a_arg_offset-1+a_arg_size]); + } + + while (b_arg_size>0){ + --b_arg_size; + s_push_b (graph_p[a_size+b_arg_offset-1+b_arg_size]); + } +} + +extern int profile_flag; +extern LABEL *profile_function_label; + +void code_pd (void) +{ + profile_flag=PROFILE_DOUBLE; +} + +void code_pe (void) +{ + profile_function_label=NULL; +} + +void code_pl (void) +{ + profile_flag=PROFILE_CURRIED; +} + +void code_pld (void) +{ + profile_flag=PROFILE_CURRIED_DOUBLE; +} + +void code_pn (void) +{ + profile_flag=PROFILE_NOT; +} + +void code_pt (void) +{ + profile_flag=PROFILE_TAIL; +} + +static int in_out_stack_offset=0; + +#ifdef G_POWER +# define REGISTER_R3 (-21) +#endif + +void code_in (char parameters[]) +{ + /* [Rn] [On]+ [W|L|S|SDn|C([Dn|Sn]+)|An|Dn] */ + +#if defined (M68000) || defined (G_POWER) + register char *p; + register int first_parameter_offset; + int n_data_parameter_registers; + + if (parallel_flag && system_sp_label==NULL) + system_sp_label=enter_label ("system_sp",IMPORT_LABEL); + + end_basic_block_with_registers (offered_a_stack_size,offered_b_stack_size,offered_vector); + + begin_new_basic_block(); + + if (parallel_flag){ + n_data_parameter_registers=N_DATA_PARAMETER_REGISTERS-1; + i_move_r_r (B_STACK_POINTER,REGISTER_A3); + i_move_l_r (system_sp_label,B_STACK_POINTER); + } else + n_data_parameter_registers=N_DATA_PARAMETER_REGISTERS; + + if (offered_b_stack_size<=n_data_parameter_registers) + in_out_stack_offset=0; + else + in_out_stack_offset=(offered_b_stack_size-n_data_parameter_registers)<<2; + /* in_out_stack_offset only correct when there are no reals ! */ + + first_parameter_offset=0; + + p=parameters; + while (*p!=0){ + register int offset,stack; + + stack=*p++ & ~0x20; + offset=*p++; + + if (*p=='R'){ + int n; + + ++p; + n=(unsigned char)*p++; + n=(n<<8)+(unsigned char)*p++; + + if (n!=0){ + i_sub_i_r (n,B_STACK_POINTER); + first_parameter_offset+=n; + } + } + + while (*p=='O'){ + int n; +#ifdef G_POWER + int d_register; +#endif + ++p; + n=*p++; + n=(n<<8)+*p++; +#ifdef G_POWER + d_register=*p++; + i_lea_id_r (n,B_STACK_POINTER,REGISTER_R3+d_register); +#else + if (n!=0){ + i_word_i (0x486F); + i_word_i (n); + } else + i_word_i (0x2F0F); + + first_parameter_offset+=4; +#endif + } + + switch (*p){ + case 'W': + { + register int n_registers; + + if (stack=='A'){ + n_registers=offered_a_stack_size; + if (n_registers>N_ADDRESS_PARAMETER_REGISTERS) + n_registers=N_ADDRESS_PARAMETER_REGISTERS; +#ifdef G_POWER + if (offset<n_registers) + i_movew_r_idu (num_to_a_reg (n_registers-offset-1),-2,B_STACK_POINTER); + else + i_movew_id_idu ((offset-n_registers)<<2,A_STACK_POINTER,-2,B_STACK_POINTER); +#else + if (offset<n_registers) + i_movew_r_pd (num_to_a_reg (n_registers-offset-1),REGISTER_A7); + else + i_movew_id_pd ((offset-n_registers)<<2,A_STACK_POINTER,REGISTER_A7); +#endif + } else { + n_registers=offered_b_stack_size; + if (n_registers>n_data_parameter_registers) + n_registers=n_data_parameter_registers; +#ifdef G_POWER + if (offset<n_registers) + i_movew_r_idu (num_to_d_reg (n_registers-offset-1),-2,B_STACK_POINTER); + else + i_movew_id_idu + (first_parameter_offset+((offset-n_registers)<<2)+2,B_STACK_POINTER,-2,B_STACK_POINTER); +#else + if (offset<n_registers) + i_movew_r_pd (num_to_d_reg (n_registers-offset-1),REGISTER_A7); + else + if (!parallel_flag) + i_movew_id_pd + (first_parameter_offset+((offset-n_registers)<<2)+2,B_STACK_POINTER,REGISTER_A7); + else + i_movew_id_pd (((offset-n_registers)<<2)+2,REGISTER_A3,REGISTER_A7); +#endif + } + ++p; + first_parameter_offset+=2; + break; + } + case 'L': + { + register int n_registers; + + if (stack=='A'){ + n_registers=offered_a_stack_size; + if (n_registers>N_ADDRESS_PARAMETER_REGISTERS) + n_registers=N_ADDRESS_PARAMETER_REGISTERS; +#ifdef G_POWER + if (offset<n_registers) + i_move_r_idu (num_to_a_reg (n_registers-offset-1),-4,B_STACK_POINTER); + else + i_move_id_idu ((offset-n_registers)<<2,A_STACK_POINTER,-4,B_STACK_POINTER); +#else + if (offset<n_registers) + i_move_r_pd (num_to_a_reg (n_registers-offset-1),REGISTER_A7); + else + i_move_id_pd ((offset-n_registers)<<2,A_STACK_POINTER,REGISTER_A7); +#endif + } else { + n_registers=offered_b_stack_size; + if (n_registers>n_data_parameter_registers) + n_registers=n_data_parameter_registers; +#ifdef G_POWER + if (offset<n_registers) + i_move_r_idu (num_to_d_reg (n_registers-offset-1),-4,B_STACK_POINTER); + else + i_move_id_idu + (first_parameter_offset+((offset-n_registers)<<2),B_STACK_POINTER,-4,B_STACK_POINTER); +#else + if (offset<n_registers) + i_move_r_pd (num_to_d_reg (n_registers-offset-1),REGISTER_A7); + else + if (!parallel_flag) + i_move_id_pd + (first_parameter_offset+((offset-n_registers)<<2),B_STACK_POINTER,REGISTER_A7); + else + i_move_id_pd (((offset-n_registers)<<2),REGISTER_A3,REGISTER_A7); +#endif + } + ++p; + first_parameter_offset+=4; + break; + } + case 'S': + if (stack=='A'){ + int n_registers; + + n_registers=offered_a_stack_size; + if (n_registers>N_ADDRESS_PARAMETER_REGISTERS) + n_registers=N_ADDRESS_PARAMETER_REGISTERS; + + if (offset<n_registers){ + int areg; + + areg=num_to_a_reg (n_registers-offset-1); + ++p; +#ifdef G_POWER + i_lea_id_r (7,areg,REGISTER_R3+ *p++); +#else + i_word_i (0x4868+n_registers-offset-1); + i_word_i (7); + + first_parameter_offset+=4; +#endif + break; + } + } + error ("Error in string parameter for in instruction"); + break; + case 'C': + if (stack=='A'){ + int n_registers; + + n_registers=offered_a_stack_size; + if (n_registers>N_ADDRESS_PARAMETER_REGISTERS) + n_registers=N_ADDRESS_PARAMETER_REGISTERS; + + if (offset<n_registers){ + int areg; + + areg=num_to_a_reg (n_registers-offset-1); + ++p; + while (*p=='D' || *p=='S'){ + if (*p=='D'){ + ++p; +#ifdef G_POWER + i_lea_id_r (8,areg,REGISTER_R3+ *p++); +#else + i_word_i (0x4868+n_registers-offset-1); + i_word_i (8); + first_parameter_offset+=4; +#endif + } else { + ++p; +#ifdef G_POWER + i_move_id_r (4,areg,REGISTER_R3+ *p++); +#else + i_move_id_pd (4,areg,REGISTER_A7); + first_parameter_offset+=4; +#endif + } + } + break; + } + } + error ("Error in characters parameter for in instruction"); + break; + case 'A': + { + int n_registers; +#ifdef M68000 + n_registers=offered_a_stack_size; + if (n_registers>N_ADDRESS_PARAMETER_REGISTERS) + n_registers=N_ADDRESS_PARAMETER_REGISTERS; + + if (stack!='A' || n_registers-offset-1!=p[1]) + error ("Wrong address register for in instruction"); +#else /* for G_POWER */ + n_registers=offered_b_stack_size; + if (n_registers>n_data_parameter_registers) + n_registers=n_data_parameter_registers; + + if (stack!='B' || p[1]>N_ADDRESS_PARAMETER_REGISTERS) + error ("Wrong address register for in instruction"); + + if (offset<n_registers) + i_move_r_r (REGISTER_D0+(n_registers-offset-1),REGISTER_A0-p[1]); + else + i_move_id_r + (first_parameter_offset+((offset-n_registers)<<2),B_STACK_POINTER,REGISTER_A0-p[1]); +#endif + + p+=2; + break; + } + case 'D': + { + int n_registers; + + n_registers=offered_b_stack_size; + if (n_registers>n_data_parameter_registers) + n_registers=n_data_parameter_registers; +#ifdef M68000 + if (stack!='B' || n_registers-offset-1!=p[1]) + error ("Wrong data register for in instruction"); +#else /* for G_POWER */ + if (stack!='B' || p[1]>8) + error ("Wrong data register for in instruction"); + + if (offset<n_registers) + i_move_r_r (REGISTER_D0+(n_registers-offset-1),REGISTER_R3+p[1]); + else + i_move_id_r + (first_parameter_offset+((offset-n_registers)<<2),B_STACK_POINTER,REGISTER_R3+p[1]); +#endif + p+=2; + break; + } + case 'U': + ++p; + break; + default: + error ("Error in parameters for in instruction"); + } + } +#else + error ("ABC instruction 'in' not implemented"); +#endif +} + +static void out_parameter_error (void) +{ + error_i ("Error in parameters for out instruction at line %d",line_number); +} + +void code_out (char parameters[]) +{ + /* [Rn] [In] [W|L|Z|An|Dn] */ +#if defined (M68000) || defined (G_POWER) + register char *p; + int deschedule_count; + + deschedule_count=-1; + + p=parameters; + while (*p!=0){ + int offset,stack; + + stack=*p++; + offset=*p++; + + if (*p=='R' && deschedule_count<0){ + int n; + + ++p; + n=(unsigned char)*p++; + n=(n<<8)+(unsigned char)*p++; + + deschedule_count=n; + } + + if (*p=='I'){ + int n; + + ++p; + n=(unsigned char)*p++; + n=(n<<8)+(unsigned char)*p++; + + i_add_i_r (n,B_STACK_POINTER); + } + + switch (*p){ + case 'W': + { + int n_registers; + + if (stack=='A'){ + n_registers=offered_a_stack_size; + if (n_registers>N_ADDRESS_PARAMETER_REGISTERS) + n_registers=N_ADDRESS_PARAMETER_REGISTERS; + + if (offset<n_registers){ +#ifdef G_POWER + i_movew_id_r (0,B_STACK_POINTER,num_to_a_reg (n_registers-offset-1)); + i_add_i_r (2,B_STACK_POINTER); +#else + i_movew_pi_r (REGISTER_A7,num_to_a_reg (n_registers-offset-1)); +#endif + } else + out_parameter_error(); + /* i_movew_pi_id (REGISTER_A7,2+((offset-n_registers)<<2),A_STACK_POINTER); */ + } else { + n_registers=offered_b_stack_size; + if (n_registers>N_DATA_PARAMETER_REGISTERS) + n_registers=N_DATA_PARAMETER_REGISTERS; + + if (offset<n_registers){ + int d_register; + + d_register=num_to_d_reg (n_registers-offset-1); +#ifdef G_POWER + i_movew_id_r (0,B_STACK_POINTER,d_register); + i_add_i_r (2,B_STACK_POINTER); +#else + i_movew_pi_r (REGISTER_A7,d_register); + i_ext_r (d_register); +#endif + } else + out_parameter_error(); + /* i_movew_pi_id (REGISTER_A7,2-((1+offset-n_registers)<<2),B_STACK_POINTER); */ + } + ++p; + break; + } + case 'L': + { + int n_registers; + + if (stack=='A'){ + n_registers=offered_a_stack_size; + if (n_registers>N_ADDRESS_PARAMETER_REGISTERS) + n_registers=N_ADDRESS_PARAMETER_REGISTERS; + + if (offset<n_registers){ +#ifdef G_POWER + i_move_id_r (0,B_STACK_POINTER,num_to_a_reg (n_registers-offset-1)); + i_add_i_r (4,B_STACK_POINTER); +#else + i_move_pi_r (REGISTER_A7,num_to_a_reg (n_registers-offset-1)); +#endif + } else + out_parameter_error(); + /* i_move_pi_id (REGISTER_A7,(offset-n_registers)<<2,A_STACK_POINTER); */ + } else { + n_registers=offered_b_stack_size; + if (n_registers>N_DATA_PARAMETER_REGISTERS) + n_registers=N_DATA_PARAMETER_REGISTERS; + + if (offset<n_registers){ + int d_register; + + d_register=num_to_d_reg (n_registers-offset-1); +#ifdef G_POWER + i_move_id_r (0,B_STACK_POINTER,d_register); + i_add_i_r (4,B_STACK_POINTER); +#else + i_move_pi_r (REGISTER_A7,d_register); +#endif + } else + out_parameter_error(); + /* i_move_pi_id (REGISTER_A7,-(1+offset-n_registers)<<2,B_STACK_POINTER); */ + } + ++p; + break; + } + case 'D': +#ifdef G_POWER + { + int d_register,n_registers; + + ++p; + d_register=*p++; + + n_registers=offered_b_stack_size; + if (n_registers>N_DATA_PARAMETER_REGISTERS) + n_registers=N_DATA_PARAMETER_REGISTERS; + + if (d_register>8 || offset>=n_registers) + out_parameter_error(); + + i_move_r_r (REGISTER_R3+d_register,num_to_d_reg (n_registers-offset-1)); + } +#else + p+=2; +#endif + break; + case 'A': + p+=2; + break; + case 'Z': + { + int n_registers; + + if (stack=='A'){ + n_registers=offered_a_stack_size; + if (n_registers>N_ADDRESS_PARAMETER_REGISTERS) + n_registers=N_ADDRESS_PARAMETER_REGISTERS; + + if (offset<n_registers) + i_move_i_r (0,num_to_a_reg (n_registers-offset-1)); + else + out_parameter_error(); + } else { + n_registers=offered_b_stack_size; + if (n_registers>N_DATA_PARAMETER_REGISTERS) + n_registers=N_DATA_PARAMETER_REGISTERS; + + if (offset<n_registers) + i_move_i_r (0,num_to_d_reg (n_registers-offset-1)); + else + out_parameter_error(); + } + ++p; + break; + } + case 'B': + { + int n_registers,result_d_register; +#ifdef G_POWER + int d_register; +#endif + ++p; + + n_registers=offered_b_stack_size; + if (n_registers>N_DATA_PARAMETER_REGISTERS) + n_registers=N_DATA_PARAMETER_REGISTERS; +#ifdef G_POWER + d_register=*p++; + + if (d_register>8 || offset>=n_registers) + out_parameter_error(); + + result_d_register=num_to_d_reg (n_registers-offset-1); + i_move_r_r (REGISTER_R3+d_register,result_d_register); + i_and_i_r (1,result_d_register); + /* neg rn,rn: */ + i_word_i (0x7C0000D0|((24+result_d_register)<<21)|((24+result_d_register)<<16)); + break; +#else + if (offset<n_registers){ + result_d_register=num_to_d_reg (n_registers-offset-1); + i_move_i_r (1,result_d_register); + i_word_i (0xC01F | (result_d_register<<9)); /* and.b (sp)+,dn */ + i_word_i (0x4480 | result_d_register); /* neg.l dn */ + } else + out_parameter_error(); + break; +#endif + } + default: + out_parameter_error(); + } + } + + if (parallel_flag){ + if (in_out_stack_offset!=0) + i_add_i_r (in_out_stack_offset,REGISTER_A3); + i_move_r_r (REGISTER_A3,B_STACK_POINTER); + + if (deschedule_count>0){ + i_sub_i_r (deschedule_count,REGISTER_D6); + i_word_i (0x6404); + i_schedule_i (offered_a_stack_size<<4); + } + } else + if (in_out_stack_offset!=0) + i_add_i_r (in_out_stack_offset,B_STACK_POINTER); + + if (last_block->block_instructions!=NULL) + begin_new_basic_block(); + else { + release_a_stack(); + release_b_stack(); + } + + init_a_stack (offered_a_stack_size); + init_b_stack (offered_b_stack_size,offered_vector); +#else + error ("ABC instruction 'out' not implemented"); +#endif +} + +#ifdef ALIGN_C_CALLS +# define REGISTER_O0 (-13) +#endif + +#if defined (M68000) || defined (G_POWER) +void code_call (char *s1,int length,char *s2) +{ + LABEL *label; + +# if defined (G_POWER) && defined (MACH_O) + if (s2[0]=='.'){ + char label_name [202]; + + label_name[0]='_'; + strcpy (&label_name[1],s2+1); + + label=enter_label (label_name,0); + + if (dyld_stub_binding_helper_p_label==NULL) + dyld_stub_binding_helper_p_label=enter_label ("dyld_stub_binding_helper",IMPORT_LABEL); + } else +#endif + label=enter_label (s2,0); + +#ifdef M68000 + i_jsr_l (label,0); +#else + if (length>0 && s1[0]=='G'){ + if (saved_heap_p_label==NULL) + saved_heap_p_label=enter_label ("saved_heap_p",IMPORT_LABEL); + if (saved_a_stack_p_label==NULL) + saved_a_stack_p_label=enter_label ("saved_a_stack_p",IMPORT_LABEL); + + i_lea_l_i_r (saved_a_stack_p_label,0,REGISTER_A3); + i_move_r_id (A_STACK_POINTER,0,REGISTER_A3); + i_lea_l_i_r (saved_heap_p_label,0,REGISTER_A3); + i_move_r_id (HEAP_POINTER,0,REGISTER_A3); + i_move_r_id (REGISTER_D7,4,REGISTER_A3); + +# ifdef ALIGN_C_CALLS + i_move_r_r (B_STACK_POINTER,REGISTER_O0); + i_or_i_r (28,B_STACK_POINTER); +# endif + i_call_l (label,64); + + i_lea_l_i_r (saved_a_stack_p_label,0,REGISTER_A3); + i_move_id_r (0,REGISTER_A3,A_STACK_POINTER); + i_lea_l_i_r (saved_heap_p_label,0,REGISTER_A3); + i_move_id_r (0,REGISTER_A3,HEAP_POINTER); + i_move_id_r (4,REGISTER_A3,REGISTER_D7); + } else { +# ifdef ALIGN_C_CALLS + i_move_r_r (B_STACK_POINTER,REGISTER_O0); + i_or_i_r (28,B_STACK_POINTER); +# endif + i_call_l (label,64); + } +#endif +} +#endif + +static char ccall_error_string[] = "Error in ccall of '%s'"; + +#if defined (sparc) || defined (G_POWER) +# ifdef sparc +# define N_C_PARAMETER_REGISTERS 6 +# define C_PARAMETER_REGISTER_0 8 +# define FIRST_C_STACK_PARAMETER_WORD_OFFSET 17 +# define SP_REGISTER 14 +# else +# define N_C_PARAMETER_REGISTERS 8 +# define C_PARAMETER_REGISTER_0 (-21) +# ifdef LINUX_ELF +# define FIRST_C_STACK_PARAMETER_WORD_OFFSET (2-8-32) +# else +# ifdef ALIGN_C_CALLS +# define FIRST_C_STACK_PARAMETER_WORD_OFFSET (6-32-7) +# else +# define FIRST_C_STACK_PARAMETER_WORD_OFFSET (6-32) +# endif +# endif +# define SP_REGISTER B_STACK_POINTER +# endif +#endif + +#ifdef ALIGN_C_CALLS +# define B_STACK_REGISTER REGISTER_O0 +#else +# define B_STACK_REGISTER B_STACK_POINTER +#endif + +#if defined (G_POWER) || defined (sparc) + static void ccall_load_b_offset (int b_o,int c_parameter_n) + { + if (c_parameter_n<N_C_PARAMETER_REGISTERS) + i_lea_id_r (b_o,B_STACK_REGISTER,C_PARAMETER_REGISTER_0+c_parameter_n); + else { + i_lea_id_r (b_o,B_STACK_REGISTER,REGISTER_A3); + i_move_r_id (REGISTER_A3,(FIRST_C_STACK_PARAMETER_WORD_OFFSET+c_parameter_n)<<2,SP_REGISTER); + } + } + + static void ccall_load_string_or_array_offset (int offset,int c_parameter_n,int a_o) + { + i_move_id_r (a_o,A_STACK_POINTER,REGISTER_A0); + if (c_parameter_n<N_C_PARAMETER_REGISTERS) + i_lea_id_r (offset,REGISTER_A0,C_PARAMETER_REGISTER_0+c_parameter_n); + else { + i_lea_id_r (offset,REGISTER_A0,REGISTER_A3); + i_move_r_id (REGISTER_A3,(FIRST_C_STACK_PARAMETER_WORD_OFFSET+c_parameter_n)<<2,SP_REGISTER); + } + } +#endif + +void code_ccall (char *c_function_name,char *s,int length) +{ + LABEL *label; + int l,min_index; + int a_offset,b_offset,a_result_offset,b_result_offset; + int result,a_o,b_o,float_parameters; + int n_clean_b_register_parameters,clean_b_register_parameter_n; + int n_extra_clean_b_register_parameters,extra_float_parameters; + int first_pointer_result_index,callee_pops_arguments,save_state_in_global_variables; + int function_address_parameter; + +#if defined (sparc) || defined (G_POWER) + int c_parameter_n; +# ifdef G_POWER + int c_offset,c_fp_parameter_n; +# endif +#elif defined (I486) + int c_offset; +#else + error ("ABC instruction 'ccall' not implemented"); +#endif + + function_address_parameter=0; + + if (*s=='G'){ + ++s; + --length; + save_state_in_global_variables=1; +#if defined (I486) || defined (G_POWER) + if (saved_heap_p_label==NULL) + saved_heap_p_label=enter_label ("saved_heap_p",IMPORT_LABEL); + if (saved_a_stack_p_label==NULL) + saved_a_stack_p_label=enter_label ("saved_a_stack_p",IMPORT_LABEL); +#endif + } else + save_state_in_global_variables=0; + + if (*s=='P'){ + ++s; + --length; + callee_pops_arguments=1; + } else + callee_pops_arguments=0; + +#if defined (sparc) || defined (I486) || defined (G_POWER) + float_parameters=0; + + a_offset=0; + b_offset=0; + n_clean_b_register_parameters=0; + + for (l=0; l<length; ++l){ + switch (s[l]){ + case '-': + case ':': + min_index=l; + break; + case 'I': + b_offset+=4; + if (!float_parameters) + ++n_clean_b_register_parameters; + continue; + case 'R': + float_parameters=1; + b_offset+=8; + continue; + case 'S': + case 's': + case 'A': + a_offset+=4; + continue; + case 'O': + case 'F': + if (function_address_parameter) + error_s (ccall_error_string,c_function_name); + function_address_parameter=s[l]; + + while (l+1<length && (s[l+1]=='*' || s[l+1]=='[')){ + ++l; + if (s[l]=='['){ + ++l; + while (l<length && (unsigned)(s[l]-'0')<(unsigned)10) + ++l; + if (!(l<length && s[l]==']')) + error_s (ccall_error_string,c_function_name); + } + } + b_offset+=4; + if (!float_parameters) + ++n_clean_b_register_parameters; + continue; + default: + error_s (ccall_error_string,c_function_name); + } + break; + } + if (l>=length) + error_s (ccall_error_string,c_function_name); + + a_result_offset=0; + b_result_offset=0; + + n_extra_clean_b_register_parameters=0; + extra_float_parameters=0; + + for (++l; l<length; ++l){ + switch (s[l]){ + case 'I': + b_result_offset+=4; + continue; + case 'R': + float_parameters=1; + b_result_offset+=8; + continue; + case 'S': + a_result_offset+=4; + continue; + case ':': + if (l==min_index+1 || l==length-1) + error_s (ccall_error_string,c_function_name); + else { + int new_length; + + new_length=l; + + for (++l; l<length; ++l){ + switch (s[l]){ + case 'I': + if (!extra_float_parameters) + ++n_extra_clean_b_register_parameters; + break; + case 'R': + float_parameters=1; + extra_float_parameters=1; + break; + case 'S': + case 'A': + continue; + default: + error_s (ccall_error_string,c_function_name); + } + } + + length=new_length; + } + break; + case 'V': + if (l==min_index+1 && l!=length-1) + continue; + default: + error_s (ccall_error_string,c_function_name); + } + } + + if (n_clean_b_register_parameters>N_DATA_PARAMETER_REGISTERS){ + n_clean_b_register_parameters=N_DATA_PARAMETER_REGISTERS; + n_extra_clean_b_register_parameters=0; + } else if (n_clean_b_register_parameters+n_extra_clean_b_register_parameters>N_DATA_PARAMETER_REGISTERS) + n_extra_clean_b_register_parameters=N_DATA_PARAMETER_REGISTERS-n_clean_b_register_parameters; + + end_basic_block_with_registers (0,n_clean_b_register_parameters+n_extra_clean_b_register_parameters,e_vector); + + b_offset-=n_clean_b_register_parameters<<2; + + if (n_extra_clean_b_register_parameters!=0){ + int n,offset; + + offset=-4; + for (n=0; n<n_extra_clean_b_register_parameters-1; ++n){ +# ifdef i486 + i_move_r_pd (REGISTER_D0+n,B_STACK_POINTER); +# else + i_move_r_id (REGISTER_D0+n,offset,B_STACK_POINTER); +# endif + offset-=4; + } + +# ifdef G_POWER + i_move_r_idu (REGISTER_D0+n,offset,B_STACK_POINTER); +# elif defined (sparc) + i_move_r_id (REGISTER_D0+n,offset,B_STACK_POINTER); + i_sub_i_r (-offset,B_STACK_POINTER); +# else + i_move_r_pd (REGISTER_D0+n,B_STACK_POINTER); +# endif + } + +# ifndef sparc + c_offset=b_offset; +# endif + + if (s[min_index]=='-' && length-1!=min_index+1){ + result='V'; + first_pointer_result_index=min_index+1; + } else { + result=s[min_index+1]; + switch (result){ + case 'I': + b_result_offset-=4; + break; + case 'R': + b_result_offset-=8; + break; + case 'S': + case 'A': + a_result_offset-=4; + + } + first_pointer_result_index=min_index+2; + } +#endif + + if (!function_address_parameter){ +#if (defined (sparc) && !defined (SOLARIS)) || (defined (I486) && !defined (LINUX_ELF)) || (defined (G_POWER) && !defined (LINUX_ELF)) || defined (MACH_O) + { + char label_name [202]; + +# if defined (G_POWER) && !defined (MACH_O) + label_name[0]='.'; +# else + label_name[0]='_'; + +# endif + strcpy (&label_name[1],c_function_name); + + label=enter_label (label_name,0); + +# if defined (G_POWER) && defined (MACH_O) + if (dyld_stub_binding_helper_p_label==NULL) + dyld_stub_binding_helper_p_label=enter_label ("dyld_stub_binding_helper",IMPORT_LABEL); +# endif + } +#else + label=enter_label (c_function_name,0); +#endif + } + +#if defined (G_POWER) || defined (sparc) + { + int b_a_offset; + +# ifdef G_POWER + if (a_result_offset+b_result_offset>b_offset){ + i_sub_i_r (a_result_offset+b_result_offset-b_offset,B_STACK_POINTER); + c_offset=a_result_offset+b_result_offset; + } + b_o=c_offset-b_result_offset; +# else + b_o=b_offset-b_result_offset; +# endif + b_a_offset=b_o; + +#ifdef ALIGN_C_CALLS + i_move_r_r (B_STACK_POINTER,REGISTER_O0); + i_or_i_r (28,B_STACK_POINTER); +#endif + + c_parameter_n=(b_offset+a_offset>>2)+n_clean_b_register_parameters-(function_address_parameter=='F'); + + for (l=first_pointer_result_index; l<length; ++l){ + switch (s[l]){ + case 'I': + ccall_load_b_offset (b_o,c_parameter_n); + ++c_parameter_n; + b_o+=4; + break; + case 'R': + ccall_load_b_offset (b_o,c_parameter_n); + ++c_parameter_n; + b_o+=8; + break; + case 'S': + b_a_offset-=4; + ccall_load_b_offset (b_a_offset,c_parameter_n); + ++c_parameter_n; + break; + case 'V': + break; + default: + error_s (ccall_error_string,c_function_name); + } + } + } + + a_o=0; +# ifdef G_POWER + b_o=c_offset-b_offset; +# else + b_o=0; +# endif + c_parameter_n=0; +# ifdef G_POWER + c_fp_parameter_n=0; +# endif + + { + int function_address_reg; + + clean_b_register_parameter_n=0; + for (l=0; l<min_index; ++l){ + switch (s[l]){ + case 'I': + if (clean_b_register_parameter_n < n_clean_b_register_parameters){ + int clean_b_reg_n; + + clean_b_reg_n=REGISTER_D0+n_extra_clean_b_register_parameters+n_clean_b_register_parameters-1-clean_b_register_parameter_n; + if (c_parameter_n<N_C_PARAMETER_REGISTERS) + i_move_r_r (clean_b_reg_n,C_PARAMETER_REGISTER_0+c_parameter_n); + else + i_move_r_id (clean_b_reg_n,(FIRST_C_STACK_PARAMETER_WORD_OFFSET+c_parameter_n)<<2,SP_REGISTER); + ++c_parameter_n; + ++clean_b_register_parameter_n; + } else { + if (c_parameter_n<N_C_PARAMETER_REGISTERS) + i_move_id_r (b_o,B_STACK_REGISTER,C_PARAMETER_REGISTER_0+c_parameter_n++); + else { + i_move_id_r (b_o,B_STACK_REGISTER,REGISTER_A3); + i_move_r_id (REGISTER_A3,(FIRST_C_STACK_PARAMETER_WORD_OFFSET+c_parameter_n++)<<2,SP_REGISTER); + } + b_o+=4; + } + break; + case 'R': +# ifdef G_POWER +# ifdef LINUX_ELF + if (c_fp_parameter_n<8){ +# else + if (c_fp_parameter_n<13){ + c_parameter_n+=2; +# endif + i_fmove_id_fr (b_o,B_STACK_REGISTER,1+c_fp_parameter_n-14); + } else { +# ifdef LINUX_ELF + error_s ("Passing more than 8 fp register not implemented (in '%s')",c_function_name); +# else + i_move_id_r (b_o,B_STACK_REGISTER,REGISTER_A3); + i_move_r_id (REGISTER_A3,(FIRST_C_STACK_PARAMETER_WORD_OFFSET+c_parameter_n++)<<2,SP_REGISTER); + i_move_id_r (b_o+4,B_STACK_REGISTER,REGISTER_A3); + i_move_r_id (REGISTER_A3,(FIRST_C_STACK_PARAMETER_WORD_OFFSET+c_parameter_n++)<<2,SP_REGISTER); +# endif + } + ++c_fp_parameter_n; +# else + if (c_parameter_n<N_C_PARAMETER_REGISTERS) + i_move_id_r (b_o,B_STACK_REGISTER,C_PARAMETER_REGISTER_0+c_parameter_n++); + else { + i_move_id_r (b_o,B_STACK_REGISTER,REGISTER_A3); + i_move_r_id (REGISTER_A3,(FIRST_C_STACK_PARAMETER_WORD_OFFSET+c_parameter_n++)<<2,SP_REGISTER); + } + if (c_parameter_n<N_C_PARAMETER_REGISTERS) + i_move_id_r (b_o+4,B_STACK_REGISTER,C_PARAMETER_REGISTER_0+c_parameter_n++); + else { + i_move_id_r (b_o+4,B_STACK_REGISTER,REGISTER_A3); + i_move_r_id (REGISTER_A3,(FIRST_C_STACK_PARAMETER_WORD_OFFSET+c_parameter_n++)<<2,SP_REGISTER); + } +# endif + b_o+=8; + break; + case 'S': + a_o-=4; + ccall_load_string_or_array_offset (4,c_parameter_n,a_o); + ++c_parameter_n; + break; + case 's': + a_o-=4; + ccall_load_string_or_array_offset (8,c_parameter_n,a_o); + ++c_parameter_n; + break; + case 'A': + a_o-=4; + ccall_load_string_or_array_offset (12,c_parameter_n,a_o); + ++c_parameter_n; + break; + case 'F': + case 'O': + if (clean_b_register_parameter_n < n_clean_b_register_parameters){ + int clean_b_reg_n; + + clean_b_reg_n=REGISTER_D0+n_extra_clean_b_register_parameters+n_clean_b_register_parameters-1-clean_b_register_parameter_n; + + if (function_address_parameter=='O'){ + if (c_parameter_n<N_C_PARAMETER_REGISTERS) + i_move_r_r (clean_b_reg_n,C_PARAMETER_REGISTER_0+c_parameter_n); + else + i_move_r_id (clean_b_reg_n,(FIRST_C_STACK_PARAMETER_WORD_OFFSET+c_parameter_n)<<2,SP_REGISTER); + ++c_parameter_n; + } + + function_address_reg=clean_b_reg_n; + + while (l+1<length && (s[l+1]=='*' || s[l+1]=='[')){ + int n; + + ++l; + n=0; + + if (s[l]=='['){ + ++l; + while (l<length && (unsigned)(s[l]-'0')<(unsigned)10){ + n=n*10+(s[l]-'0'); + ++l; + } + } + + i_move_id_r (n,clean_b_reg_n,clean_b_reg_n); + } + + + ++clean_b_register_parameter_n; + break; + } + default: + error_s (ccall_error_string,c_function_name); + } + } +# ifdef G_POWER + if (save_state_in_global_variables){ + i_lea_l_i_r (saved_a_stack_p_label,0,REGISTER_A3); + i_move_r_id (A_STACK_POINTER,0,REGISTER_A3); + i_lea_l_i_r (saved_heap_p_label,0,REGISTER_A3); + i_move_r_id (HEAP_POINTER,0,REGISTER_A3); + i_move_r_id (REGISTER_D7,4,REGISTER_A3); + } + + if (!function_address_parameter) + i_call_l (label,128); + else + i_call_r (function_address_reg,128); + + if (save_state_in_global_variables){ + i_lea_l_i_r (saved_a_stack_p_label,0,REGISTER_A3); + i_move_id_r (0,REGISTER_A3,A_STACK_POINTER); + i_lea_l_i_r (saved_heap_p_label,0,REGISTER_A3); + i_move_id_r (0,REGISTER_A3,HEAP_POINTER); + i_move_id_r (4,REGISTER_A3,REGISTER_D7); + } + + begin_new_basic_block(); /* MTLR/MFLR optimization only finds IJSR at end of basic block */ +# else + if (!function_address_parameter) + i_call_l (label); + else + i_call_r (function_address_reg); +# endif + } + + if (a_offset!=0) + i_add_i_r (-a_offset,A_STACK_POINTER); +# ifdef G_POWER + if (c_offset-(b_result_offset+a_result_offset)!=0) + i_add_i_r (c_offset-(b_result_offset+a_result_offset),B_STACK_POINTER); +# else + if (b_offset-(b_result_offset+a_result_offset)!=0) + i_add_i_r (b_offset-(b_result_offset+a_result_offset),B_STACK_POINTER); +# endif + + for (l=first_pointer_result_index; l<length; ++l){ + switch (s[l]){ + case 'I': + case 'R': + break; + case 'S': + if (string_to_string_node_label==NULL) + string_to_string_node_label=enter_label ("string_to_string_node",IMPORT_LABEL); + + i_move_id_r (0,B_STACK_POINTER,REGISTER_A0); + i_jsr_l_id (string_to_string_node_label,0); + i_move_r_id (REGISTER_A0,0,A_STACK_POINTER); + i_add_i_r (4,A_STACK_POINTER); + break; + case 'V': + break; + default: + error_s (ccall_error_string,c_function_name); + } + } + + switch (result){ + case 'I': + i_move_r_r (C_PARAMETER_REGISTER_0,REGISTER_D0); + begin_new_basic_block(); + init_b_stack (1,i_vector); + break; + case 'R': +#ifdef G_POWER + i_fmove_fr_fr (1-14,0); +#endif + begin_new_basic_block(); + init_b_stack (2,r_vector); + break; + case 'S': + if (string_to_string_node_label==NULL) + string_to_string_node_label=enter_label ("string_to_string_node",IMPORT_LABEL); + + i_move_r_r (C_PARAMETER_REGISTER_0,REGISTER_A0); + i_sub_i_r (4,B_STACK_POINTER); + i_jsr_l_id (string_to_string_node_label,0); + + begin_new_basic_block(); + init_a_stack (1); + break; + case 'V': + begin_new_basic_block(); + break; + default: + error_s (ccall_error_string,c_function_name); + } +#elif defined (I486) + { + int c_offset_before_pushing_arguments,function_address_reg; + + a_o=-b_result_offset-a_result_offset; + b_o=0; + + if (a_result_offset+b_result_offset>b_offset){ + i_sub_i_r (a_result_offset+b_result_offset-b_offset,B_STACK_POINTER); + c_offset=a_result_offset+b_result_offset; + } + + c_offset_before_pushing_arguments=c_offset; + + for (l=length-1; l>=first_pointer_result_index; --l){ + switch (s[l]){ + case 'I': + b_o-=4; + i_lea_id_r (b_o+c_offset,B_STACK_POINTER,REGISTER_A0); + i_move_r_pd (REGISTER_A0,B_STACK_POINTER); + c_offset+=4; + break; + case 'R': + b_o-=8; + i_lea_id_r (b_o+c_offset,B_STACK_POINTER,REGISTER_A0); + i_move_r_pd (REGISTER_A0,B_STACK_POINTER); + c_offset+=4; + break; + case 'S': + i_lea_id_r (a_o+c_offset,B_STACK_POINTER,REGISTER_A0); + i_move_r_pd (REGISTER_A0,B_STACK_POINTER); + a_o+=4; + c_offset+=4; + break; + case 'V': + break; + default: + error_s (ccall_error_string,c_function_name); + } + } + + { + int last_register_parameter_index,reg_n; + + last_register_parameter_index=-1; + + reg_n=0; + l=0; + while (reg_n<n_clean_b_register_parameters && l<min_index){ + if (s[l]=='I' || s[l]=='F' || s[l]=='O'){ + ++reg_n; + last_register_parameter_index=l; + } + ++l; + } + + reg_n=0; + a_o=-a_offset; + b_o=0; + for (l=min_index-1; l>=0; --l){ + switch (s[l]){ + case 'I': + if (l<=last_register_parameter_index){ + i_move_r_pd (REGISTER_D0+n_extra_clean_b_register_parameters+reg_n,B_STACK_POINTER); + ++reg_n; + } else { + b_o-=4; + i_move_id_pd (b_o+c_offset,B_STACK_POINTER,B_STACK_POINTER); + } + c_offset+=4; + break; + case 'R': + b_o-=8; + i_move_id_pd (b_o+c_offset+4,B_STACK_POINTER,B_STACK_POINTER); + i_move_id_pd (b_o+(c_offset+4),B_STACK_POINTER,B_STACK_POINTER); + c_offset+=8; + break; + case 'S': + i_move_id_r (a_o,A_STACK_POINTER,REGISTER_A0); + i_add_i_r (4,REGISTER_A0); + i_move_r_pd (REGISTER_A0,B_STACK_POINTER); + a_o+=4; + c_offset+=4; + break; + case 's': + i_move_id_r (a_o,A_STACK_POINTER,REGISTER_A0); + i_add_i_r (8,REGISTER_A0); + i_move_r_pd (REGISTER_A0,B_STACK_POINTER); + a_o+=4; + c_offset+=4; + break; + case 'A': + i_move_id_r (a_o,A_STACK_POINTER,REGISTER_A0); + i_add_i_r (12,REGISTER_A0); + i_move_r_pd (REGISTER_A0,B_STACK_POINTER); + a_o+=4; + c_offset+=4; + break; + case 'F': + case 'O': + case '*': + case ']': + /* while (l>=0 && !(s[l]=='F' || s[l]=='O')) bug in watcom c */ + while (l>=0 && (s[l]!='F' && s[l]!='O')) + --l; + + if (l<=last_register_parameter_index){ + int clean_b_reg_n,i; + + clean_b_reg_n=REGISTER_D0+n_extra_clean_b_register_parameters+reg_n; + + if (function_address_parameter=='O'){ + i_move_r_pd (clean_b_reg_n,B_STACK_POINTER); + c_offset+=4; + } + + ++reg_n; + + function_address_reg=clean_b_reg_n; + i=l; + while (i+1<length && (s[i+1]=='*' || s[i+1]=='[')){ + int n; + + ++i; + n=0; + + if (s[i]=='['){ + ++i; + while (i<length && (unsigned)(s[i]-'0')<(unsigned)10){ + n=n*10+(s[i]-'0'); + ++i; + } + } + + i_move_id_r (n,clean_b_reg_n,clean_b_reg_n); + } + break; + } + default: + error_s (ccall_error_string,c_function_name); + } + } + } + + if (float_parameters){ +#if 1 + int freg_n; + + for (freg_n=0; freg_n<8; ++freg_n){ + i_word_i (0xdd); + i_word_i (0xc0+freg_n); + } +#else + i_word_i (0xdb); + i_word_i (0xe3); +#endif + } + + if (save_state_in_global_variables){ + i_move_r_l (-4/*ESI*/,saved_a_stack_p_label); + i_move_r_l (-5/*EDI*/,saved_heap_p_label); + } + + if (!function_address_parameter) + i_jsr_l (label,0); + else + i_jsr_r (function_address_reg); + + if (save_state_in_global_variables){ + i_move_l_r (saved_a_stack_p_label,-4/*ESI*/); + i_move_l_r (saved_heap_p_label,-5/*EDI*/); + } + + if (callee_pops_arguments) + c_offset=c_offset_before_pushing_arguments; + + if (a_offset!=0) + i_sub_i_r (a_offset,A_STACK_POINTER); + if (c_offset-(b_result_offset+a_result_offset)!=0) + i_add_i_r (c_offset-(b_result_offset+a_result_offset),B_STACK_POINTER); + + } + + for (l=length-1; l>=first_pointer_result_index; --l){ + switch (s[l]){ + case 'I': + case 'R': + break; + case 'S': + if (string_to_string_node_label==NULL) + string_to_string_node_label=enter_label ("string_to_string_node",IMPORT_LABEL); + i_move_pi_r (B_STACK_POINTER,REGISTER_A0); + i_jsr_l (string_to_string_node_label,0); + i_move_r_id (REGISTER_A0,0,A_STACK_POINTER); + i_add_i_r (4,A_STACK_POINTER); + break; + case 'V': + break; + default: + error_s (ccall_error_string,c_function_name); + } + } + + switch (result){ + case 'I': + begin_new_basic_block(); + init_b_stack (1,i_vector); + break; + case 'R': + begin_new_basic_block(); + init_b_stack (2,r_vector); + break; + case 'S': + if (string_to_string_node_label==NULL) + string_to_string_node_label=enter_label ("string_to_string_node",IMPORT_LABEL); + + i_move_r_r (REGISTER_D0,REGISTER_A0); + i_jsr_l (string_to_string_node_label,0); + + begin_new_basic_block(); + init_a_stack (1); + break; + case 'V': + begin_new_basic_block(); + break; + default: + error_s (ccall_error_string,c_function_name); + } +#endif +} + +#define SMALL_VECTOR_SIZE 32 +#define LOG_SMALL_VECTOR_SIZE 5 +#define MASK_SMALL_VECTOR_SIZE 31 + +static char centry_error_string[]="Error in c entry of '%s'"; + +#ifdef G_POWER +extern struct instruction *last_instruction; +extern LABEL *INT_label,*BOOL_label,*CHAR_label,*REAL_label; +extern LABEL *cycle_in_spine_label,*reserve_label; +void code_jsr_from_c_to_clean (char *label_name); +#endif + +void code_centry (char *c_function_name,char *clean_function_label,char *s,int length) +{ +#if defined (I486) || defined (G_POWER) + struct block_label *new_label; + LABEL *label; + int i,n,n_integer_parameters,n_integer_results,callee_pops_arguments; + + if (saved_heap_p_label==NULL) + saved_heap_p_label=enter_label ("saved_heap_p",IMPORT_LABEL); + if (saved_a_stack_p_label==NULL) + saved_a_stack_p_label=enter_label ("saved_a_stack_p",IMPORT_LABEL); + + n_integer_parameters=0; + n_integer_results=0; + + i=0; + callee_pops_arguments=0; + if (length>0 && s[0]=='P'){ + i=1; + callee_pops_arguments=1; + } + + while (i<length){ + char c; + + c=s[i]; + if (c=='I') + ++n_integer_parameters; + else if (c==':'){ + while (++i<length){ + c=s[i]; + if (c=='I') + ++n_integer_results; + else + error_s (centry_error_string,c_function_name); + } + if (n_integer_results!=1) + error_s (centry_error_string,c_function_name); + break; + } else + error_s (centry_error_string,c_function_name); + + ++i; + } + +# if (defined (sparc) && !defined (SOLARIS)) || (defined (I486) && !defined (LINUX_ELF)) || (defined (G_POWER) && !defined (LINUX_ELF)) || defined (MACH_O) + { + char label_name [202]; + +# if defined (G_POWER) && !defined (MACH_O) + label_name[0]='.'; +# else + label_name[0]='_'; +# endif + strcpy (&label_name[1],c_function_name); + + label=enter_label (label_name,EXPORT_LABEL); + +# if defined (G_POWER) && defined (MACH_O) + if (dyld_stub_binding_helper_p_label==NULL) + dyld_stub_binding_helper_p_label=enter_label ("dyld_stub_binding_helper",IMPORT_LABEL); +# endif + } +# else + label=enter_label (c_function_name,EXPORT_LABEL); +# endif + + new_label=fast_memory_allocate_type (struct block_label); + new_label->block_label_label=label; + new_label->block_label_next=NULL; + + label->label_a_stack_size=0; + label->label_b_stack_size=0; + label->label_vector=e_vector; + label->label_flags |= REGISTERS_ALLOCATED; + + generate_code_for_previous_blocks (0); + + if (last_block->block_instructions!=NULL){ + begin_new_basic_block(); + + last_block->block_begin_module=1; + last_block->block_link_module=0; + } else { + release_a_stack(); + release_b_stack(); + + if (!last_block->block_begin_module){ + last_block->block_begin_module=1; + last_block->block_link_module=0; + } + } + +# if defined (I486) + i_sub_i_r (20,B_STACK_POINTER); + + i_move_r_id (-4/*ESI*/,16,B_STACK_POINTER); + i_move_l_r (saved_a_stack_p_label,-4/*ESI*/); + + i_move_r_id (-5/*EDI*/,12,B_STACK_POINTER); + i_move_l_r (saved_heap_p_label,-5/*EDI*/); + + i_move_r_id (1/*EBX*/,8,B_STACK_POINTER); + i_move_r_id (-1/*ECX*/,4,B_STACK_POINTER); + i_move_r_id (-3/*EBP*/,0,B_STACK_POINTER); +# elif defined (G_POWER) + { + int i,offset; + + i_sub_i_r (((32-13)<<2)+((32-14)<<3),B_STACK_POINTER); + + offset=0; + for (i=13; i<32; ++i){ + i_move_r_id (i-24,offset,B_STACK_POINTER); + offset+=4; + } + + for (i=14; i<32; ++i){ + i_fmove_fr_id (i-14,offset,B_STACK_POINTER); + offset+=8; + } + } + + i_lea_l_i_r (saved_a_stack_p_label,0,REGISTER_A3); + i_move_id_r (0,REGISTER_A3,A_STACK_POINTER); + i_lea_l_i_r (saved_heap_p_label,0,REGISTER_A3); + i_move_id_r (0,REGISTER_A3,HEAP_POINTER); + i_move_id_r (4,REGISTER_A3,REGISTER_D7); +# endif + + if (last_block->block_labels==NULL) + last_block->block_labels=new_label; + else + last_block_label->block_label_next=new_label; + last_block_label=new_label; + + begin_new_basic_block(); + + last_block->block_begin_module=0; + last_block->block_link_module=1; + + reachable=1; + + init_a_stack (0); + init_b_stack (0,e_vector); + + for (n=0; n<n_integer_parameters; ++n) +#ifdef G_POWER + s_push_b (g_g_register (C_PARAMETER_REGISTER_0+((n_integer_parameters-1)-n))); +#else + s_push_b (s_get_b (5+1+(n_integer_parameters-1))); +#endif + + { + ULONG *vector_p; + static ULONG small_vector; + + if (n_integer_parameters+1<=SMALL_VECTOR_SIZE){ + small_vector=0; + vector_p=&small_vector; + } else { + int n_ulongs; + + n_ulongs=(n_integer_parameters+1+SMALL_VECTOR_SIZE-1)>>LOG_SMALL_VECTOR_SIZE; + vector_p=(ULONG*)fast_memory_allocate (n_ulongs * sizeof (ULONG)); + + for (i=0; i<n_ulongs; ++i) + vector_p[i]=0; + } + + code_d (0,n_integer_parameters,vector_p); + +#ifdef G_POWER + /* + lea a5,__cycle__in__spine + lea int_reg,INT2 + lea char_reg,CHAR2 + lea real_reg,REAL2 + lea bool_reg,BOOL2 + */ + + if (INT_label==NULL) + INT_label=enter_label ("INT",IMPORT_LABEL | DATA_LABEL); + + i_lea_l_i_r (INT_label,2,INT_REGISTER); + + if (CHAR_label==NULL) + CHAR_label=enter_label ("CHAR",IMPORT_LABEL | DATA_LABEL); + + i_lea_l_i_r (CHAR_label,2,CHAR_REGISTER); + + if (REAL_label==NULL) + REAL_label=enter_label ("REAL",IMPORT_LABEL | DATA_LABEL); + + i_lea_l_i_r (REAL_label,2,REAL_REGISTER); + + if (BOOL_label==NULL) + BOOL_label=enter_label ("BOOL",IMPORT_LABEL | DATA_LABEL); + + i_lea_l_i_r (BOOL_label,2,BOOL_REGISTER); + + if (!parallel_flag){ + if (cycle_in_spine_label==NULL){ + cycle_in_spine_label=enter_label ("__cycle__in__spine",IMPORT_LABEL | NODE_ENTRY_LABEL); + cycle_in_spine_label->label_arity=0; + cycle_in_spine_label->label_descriptor=EMPTY_label; + } + + i_lea_l_i_r (cycle_in_spine_label,0,REGISTER_A5); + } else { + if (reserve_label==NULL){ + reserve_label=enter_label ("__reserve",IMPORT_LABEL | NODE_ENTRY_LABEL); + reserve_label->label_arity=0; + reserve_label->label_descriptor=EMPTY_label; + } + i_lea_l_i_r (reserve_label,0,REGISTER_A5); + } + + code_jsr_from_c_to_clean (clean_function_label); +#else + code_jsr (clean_function_label); +#endif + + code_o (0,1,i_vector); + +# if defined (I486) + i_move_r_l (-4/*ESI*/,saved_a_stack_p_label); + i_move_id_r (16,B_STACK_POINTER,-4/*ESI*/); + + i_move_r_l (-5/*EDI*/,saved_heap_p_label); + i_move_id_r (12,B_STACK_POINTER,-5/*EDI*/); + + i_move_id_r (8,B_STACK_POINTER,1/*EBX*/); + i_move_id_r (4,B_STACK_POINTER,-1/*ECX*/); + i_move_id_r (0,B_STACK_POINTER,-3/*EBP*/); + i_add_i_r (20,B_STACK_POINTER); +# elif defined (G_POWER) + i_lea_l_i_r (saved_a_stack_p_label,0,REGISTER_A3); + i_move_r_id (A_STACK_POINTER,0,REGISTER_A3); + i_lea_l_i_r (saved_heap_p_label,0,REGISTER_A3); + i_move_r_id (HEAP_POINTER,0,REGISTER_A3); + i_move_r_id (REGISTER_D7,4,REGISTER_A3); + + i_move_r_r (REGISTER_D0,C_PARAMETER_REGISTER_0); + + { + int i,offset; + + offset=0; + for (i=13; i<32; ++i){ + i_move_id_r (offset,B_STACK_POINTER,i-24); + offset+=4; + } + + for (i=14; i<32; ++i){ + i_fmove_id_fr (offset,B_STACK_POINTER,i-14); + offset+=8; + } + + i_add_i_r (offset,B_STACK_POINTER); + } +# endif + + /* + code_d (0,1,i_vector); + code_rtn(); + */ + + { + int b_offset,a_stack_size,b_stack_size; + ULONG *local_demanded_vector; + + a_stack_size=0; + b_stack_size=1; + local_demanded_vector=i_vector; + +#if ! (defined (sparc)) + b_offset=0; +#else + b_offset=4; +#endif + + b_offset+=end_basic_block_with_registers_and_return_b_stack_offset (a_stack_size,b_stack_size,local_demanded_vector,N_ADDRESS_PARAMETER_REGISTERS); + +#if ! (defined (sparc) || defined (G_POWER)) + if (b_offset!=0) + if (b_offset>0) + i_add_i_r (b_offset,B_STACK_POINTER); + else + i_sub_i_r (-b_offset,B_STACK_POINTER); + +# ifdef I486 + if (callee_pops_arguments && n_integer_parameters>0) + i_rts_i (n_integer_parameters<<2); + else +# endif + i_rts(); +#else +# ifdef G_POWER + if (b_offset!=0) + if (b_offset>0) + i_add_i_r (b_offset,B_STACK_POINTER); + else + i_sub_i_r (-b_offset,B_STACK_POINTER); + i_rts_c(); +# else + i_rts (b_offset-4,b_offset); +# endif +#endif + reachable=0; + + begin_new_basic_block(); + } + + } +#endif +} + +void code_new_int_reducer (char label_name[],int a_offset) +{ + LABEL *reducer_label; + INSTRUCTION_GRAPH graph_1,graph_2; + +#ifdef RESERVE_NEW_REDUCER + INSTRUCTION_GRAPH graph_3; + LABEL *node_entry_label; +#endif + + if (new_int_reducer_label==NULL) + new_int_reducer_label=enter_label ("new_int_reducer",IMPORT_LABEL); + + reducer_label=enter_label (label_name,0); + + graph_1=s_get_a (a_offset); + graph_2=g_lea (reducer_label); + +#ifdef RESERVE_NEW_REDUCER + if (EMPTY_label==NULL) + EMPTY_label=enter_label ("EMPTY",IMPORT_LABEL | DATA_LABEL); + + switch (graph_1->instruction_code){ + case GFILL: + graph_3=graph_1->instruction_parameters[1].p; + if (graph_3->instruction_code==GLEA){ + node_entry_label=graph_3->instruction_parameters[0].l; + if (node_entry_label->label_flags & NODE_ENTRY_LABEL){ + char cycle_in_spine_label_n [64]; + LABEL *cycle_label_n; + int n_arguments; + + n_arguments=node_entry_label->label_arity; + + sprintf (cycle_in_spine_label_n,"_c%d",n_arguments); + cycle_label_n=enter_label (cycle_in_spine_label_n,NODE_ENTRY_LABEL | IMPORT_LABEL); + cycle_label_n->label_arity=n_arguments; + cycle_label_n->label_descriptor=EMPTY_label; + + graph_1->instruction_parameters[1].p=g_lea (cycle_label_n); + break; + } + } + graph_3=NULL; + break; + case GCREATE: + graph_3=graph_1->instruction_parameters[0].p; + if (graph_3->instruction_code==GLEA){ + node_entry_label=graph_3->instruction_parameters[0].l; + if (node_entry_label->label_flags & NODE_ENTRY_LABEL){ + char cycle_in_spine_label_n [64]; + LABEL *cycle_label_n; + int n_arguments; + + n_arguments=node_entry_label->label_arity; + + sprintf (cycle_in_spine_label_n,"_c%d",n_arguments); + cycle_label_n=enter_label (cycle_in_spine_label_n,NODE_ENTRY_LABEL | IMPORT_LABEL); + cycle_label_n->label_arity=n_arguments; + cycle_label_n->label_descriptor=EMPTY_label; + + graph_1->instruction_parameters[0].p=g_lea (cycle_label_n); + break; + } + } + default: + graph_3=NULL; + } + + if (graph_3==NULL) + error ("error: argument of new_int_reducer is not a closure"); +#endif + + s_push_a (graph_1); + + s_push_b (NULL); + s_push_b (graph_2); + +#ifdef RESERVE_NEW_REDUCER + s_push_b (graph_3); + insert_basic_block (JSR_BLOCK,1,2+1,i_i_i_vector,new_int_reducer_label); +#else + insert_basic_block (JSR_BLOCK,1,1+1,i_i_vector,new_int_reducer_label); +#endif +} + +void code_set_defer (int a_offset) +{ + INSTRUCTION_GRAPH graph_1,graph_2; + LABEL *node_entry_label; + + if (EMPTY_label==NULL) + EMPTY_label=enter_label ("EMPTY",IMPORT_LABEL | DATA_LABEL); + + graph_1=s_get_a (a_offset); + + switch (graph_1->instruction_code){ + case GFILL: + graph_2=graph_1->instruction_parameters[1].p; + if (graph_2->instruction_code==GLEA){ + node_entry_label=graph_2->instruction_parameters[0].l; + if (node_entry_label->label_flags & NODE_ENTRY_LABEL){ + LABEL *label; +#ifdef RESERVE_NEW_REDUCER + label=new_local_label (DEFERED_LABEL | NODE_ENTRY_LABEL); +#else + label=new_local_label (DEFERED_LABEL); +#endif + label->label_arity=node_entry_label->label_arity; + label->label_descriptor=node_entry_label; + + graph_1->instruction_parameters[1].p=g_lea (label); + return; + } + } + break; + case GCREATE: + graph_2=graph_1->instruction_parameters[0].p; + if (graph_2->instruction_code==GLEA){ + node_entry_label=graph_2->instruction_parameters[0].l; + if (node_entry_label->label_flags & NODE_ENTRY_LABEL){ + LABEL *label; + +#ifdef RESERVE_NEW_REDUCER + label=new_local_label (DEFERED_LABEL | NODE_ENTRY_LABEL); +#else + label=new_local_label (DEFERED_LABEL); +#endif + label->label_arity=node_entry_label->label_arity; + label->label_descriptor=node_entry_label; + + graph_1->instruction_parameters[0].p=g_lea (label); + return; + } + } + } + + error ("error: argument of set_defer is not a closure"); +} + +void code_channelP (int a_offset) +{ + INSTRUCTION_GRAPH graph_1; + + if (channelP_label==NULL) + channelP_label=enter_label ("channelP",IMPORT_LABEL); + + graph_1=s_get_a (a_offset); + + s_push_a (graph_1); + s_push_b (NULL); + insert_basic_block (JSR_BLOCK,1,0+1,i_vector,channelP_label); + + init_b_stack (1,i_vector); +} + +void code_stop_reducer (VOID) +{ + if (stop_reducer_label==NULL) + stop_reducer_label=enter_label ("stop_reducer",IMPORT_LABEL); + + end_basic_block_with_registers (0,0,e_vector); + + i_jmp_l (stop_reducer_label,0); + + reachable=0; + + begin_new_basic_block(); +} + +void code_send_graph (char descriptor_name[],int a_offset_1,int a_offset_2) +{ + INSTRUCTION_GRAPH graph_1,graph_2,graph_3; + LABEL *descriptor_label; + + if (send_graph_label==NULL) + send_graph_label=enter_label ("send_graph",IMPORT_LABEL); + +#ifdef SMALL_LAZY_DESCRIPTORS + { + char h_descriptor_name[257]; + + strcpy (h_descriptor_name,descriptor_name); + strcat (h_descriptor_name,"#"); + + descriptor_label=enter_label (h_descriptor_name,DATA_LABEL); + } +#else + descriptor_label=enter_label (descriptor_name,0); +#endif + + graph_1=g_lea (descriptor_label); + graph_2=s_get_a (a_offset_1); + graph_3=s_get_a (a_offset_2); + + s_push_a (graph_2); + s_push_a (graph_3); + + s_push_b (NULL); + s_push_b (graph_1); + insert_basic_block (JSR_BLOCK,2,1+1,i_i_vector,send_graph_label); +} + +void code_send_request (int a_offset) +{ + INSTRUCTION_GRAPH graph_1; + + if (send_request_label==NULL) + send_request_label=enter_label ("send_request",IMPORT_LABEL); + + graph_1=s_get_a (a_offset); + + s_push_a (graph_1); + + s_push_b (NULL); + insert_basic_block (JSR_BLOCK,1,0+1,e_vector,send_request_label); +} + +void code_set_continue (int a_offset) +{ + LABEL *reducer_label; + INSTRUCTION_GRAPH graph_1,graph_2; + + if (new_int_reducer_label==NULL) + new_int_reducer_label=enter_label ("new_int_reducer",IMPORT_LABEL); + + reducer_label=enter_label ("__nf__reducer",0); + + graph_1=s_get_a (a_offset); + graph_2=g_lea (reducer_label); + + s_push_a (graph_1); + + s_push_b (NULL); + s_push_b (graph_2); + + insert_basic_block (JSR_BLOCK,1,1+1,i_i_vector,new_int_reducer_label); +} + +void code_copy_graph (int a_offset) +{ + INSTRUCTION_GRAPH graph_1; + + if (copy_graph_label==NULL) + copy_graph_label=enter_label ("copy_graph",IMPORT_LABEL); + + graph_1=s_get_a (a_offset); + s_push_a (graph_1); + + s_push_b (NULL); + insert_basic_block (JSR_BLOCK,1,0+1,e_vector,copy_graph_label); + + init_a_stack (1); +} + +void code_create_channel (char *label_name) +{ + INSTRUCTION_GRAPH graph_1,graph_2; + LABEL *label; + + if (CHANNEL_label==NULL) + CHANNEL_label=enter_label ("CHANNEL",DATA_LABEL); + if (create_channel_label==NULL) + create_channel_label=enter_label ("create_channel",IMPORT_LABEL); + + label=enter_label (label_name,NODE_ENTRY_LABEL); + label->label_arity=1; + label->label_descriptor=CHANNEL_label; + + graph_1=s_pop_b(); + graph_2=g_lea (label); + + s_push_b (NULL); + s_push_b (graph_1); + s_push_b (graph_2); + + insert_basic_block (JSR_BLOCK,0,2+1,i_i_i_vector,create_channel_label); + + init_a_stack (1); +} + +void code_currentP (void) +{ + if (currentP_label==NULL) + currentP_label=enter_label ("currentP",IMPORT_LABEL); + + s_push_b (NULL); + insert_basic_block (JSR_BLOCK,0,0+1,i_vector,currentP_label); + + init_b_stack (1,i_vector); +} + +void code_new_ext_reducer (char descriptor_name[],int a_offset) +{ +#pragma unused (descriptor_name,a_offset) +/* + LABEL *descriptor_label; + INSTRUCTION_GRAPH graph_1,graph_2; + + if (new_ext_reducer_label==NULL) + new_ext_reducer_label=enter_label ("new_ext_reducer",IMPORT_LABEL); + + descriptor_label=enter_label (descriptor_name,0); + + graph_1=s_get_a (a_offset); + graph_2=g_lea (descriptor_label); + + s_push_a (graph_1); + + s_push_b (NULL); + s_push_b (graph_2); + + insert_basic_block (JSR_BLOCK,1,1+1,i_i_vector,new_ext_reducer_label); +*/ +} + +void code_newP (void) +{ + if (newP_label==NULL) + newP_label=enter_label ("newP",IMPORT_LABEL); + + s_push_b (NULL); + insert_basic_block (JSR_BLOCK,0,0+1,i_vector,newP_label); + + init_b_stack (1,i_vector); +} + +void code_parallel (VOID) +{ +} + +void code_pause (VOID) +{ + error ("ABC instruction 'pause' not implemented"); +} + +void code_randomP (void) +{ + if (randomP_label==NULL) + randomP_label=enter_label ("randomP",IMPORT_LABEL); + + s_push_b (NULL); + insert_basic_block (JSR_BLOCK,0,0+1,i_vector,randomP_label); + + init_b_stack (1,i_vector); +} + +void code_suspend (VOID) +{ + if (suspend_label==NULL) + suspend_label=enter_label ("suspend",IMPORT_LABEL); + + s_push_b (NULL); + insert_basic_block (JSR_BLOCK,0,0+1,i_vector,suspend_label); +} + +void code_add_args (int source_offset,int n_arguments,int destination_offset) +{ +# pragma unused (source_offset,n_arguments,destination_offset) + + error ("ABC instruction 'add_args' not implemented"); +} + +void code_dummy (VOID) +{ +} + +extern LABEL *cat_string_label; + +void code_catS (int source_offset_1,int source_offset_2,int destination_offset) +{ + INSTRUCTION_GRAPH graph_1,graph_2,graph_3; + + if (cat_string_label==NULL) + cat_string_label=enter_label ("cat_string",IMPORT_LABEL); + + graph_1=s_get_a (source_offset_1); + graph_2=s_get_a (source_offset_2); + graph_3=s_get_a (destination_offset); + + s_push_a (graph_3); + s_push_a (graph_2); + s_push_a (graph_1); + + s_push_b (NULL); + + insert_basic_block (JSR_BLOCK,3,0+1,e_vector,cat_string_label); +} + +void init_cginstructions (void) +{ + if (check_stack){ + if (parallel_flag){ + realloc_0_label=enter_label ("realloc_0",IMPORT_LABEL); + realloc_1_label=enter_label ("realloc_1",IMPORT_LABEL); + realloc_2_label=enter_label ("realloc_2",IMPORT_LABEL); + realloc_3_label=enter_label ("realloc_3",IMPORT_LABEL); + } else { + stack_overflow_label=enter_label ("stack_overflow",IMPORT_LABEL); + stack_overflow_label->label_id=next_label_id++; + } +#ifdef I486 + end_a_stack_label=enter_label ("end_a_stack",IMPORT_LABEL); + end_a_stack_label->label_id=next_label_id++; + end_b_stack_label=enter_label ("end_b_stack",IMPORT_LABEL); + end_b_stack_label->label_id=next_label_id++; +#endif + } + + if (parallel_flag){ + schedule_0_label=enter_label ("schedule_0",IMPORT_LABEL); + schedule_1_label=enter_label ("schedule_1",IMPORT_LABEL); + schedule_2_label=enter_label ("schedule_2",IMPORT_LABEL); + schedule_3_label=enter_label ("schedule_3",IMPORT_LABEL); + schedule_eval_label=enter_label ("schedule_eval",IMPORT_LABEL); + } + + profile_function_label=NULL; + profile_flag=PROFILE_NORMAL; + +#if defined (G_POWER) || defined (I486) + profile_l_label=NULL; + profile_l2_label=NULL; + profile_n_label=NULL; + profile_n2_label=NULL; + profile_s_label=NULL; + profile_s2_label=NULL; + profile_r_label=NULL; + profile_t_label=NULL; +# ifdef G_POWER + profile_ti_label=NULL; +# endif +#endif +#if defined (I486) || defined (G_POWER) + saved_heap_p_label=NULL; + saved_a_stack_p_label=NULL; +#endif +#ifdef MACH_O + dyld_stub_binding_helper_p_label=NULL; +#endif +} |