summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn van Groningen2008-12-18 16:12:51 +0000
committerJohn van Groningen2008-12-18 16:12:51 +0000
commit6d143de55938f32f1f53df4526e3ce869a3039ef (patch)
tree3b55bf72b2d65243fb501411ae189535ae781001
parentadd truncateR and ceilingR (diff)
add pushZ, pushZR and jmp_not_eqZ
-rw-r--r--cgcode.c98
-rw-r--r--cgcode.h1
-rw-r--r--cgcodep.h3
-rw-r--r--cginput.c238
-rw-r--r--cginstructions.c901
5 files changed, 1179 insertions, 62 deletions
diff --git a/cgcode.c b/cgcode.c
index c66e98d..a13e233 100644
--- a/cgcode.c
+++ b/cgcode.c
@@ -252,7 +252,6 @@ int no_time_profiling;
#define g_fcmp_gt(g1,g2) g_instruction_2(GFCMP_GT,(g1),(g2))
#define g_fcmp_lt(g1,g2) g_instruction_2(GFCMP_LT,(g1),(g2))
#define g_fdiv(g1,g2) g_instruction_2(GFDIV,(g1),(g2))
-
#define g_fitor(g1) g_instruction_1(GFITOR,(g1))
#ifdef I486
# define g_floordiv(g1,g2) g_instruction_2(GFLOORDIV,(g1),(g2))
@@ -289,7 +288,7 @@ int no_time_profiling;
#endif
LABEL *INT_label,*BOOL_label,*CHAR_label,*REAL_label;
-LABEL *_STRING__label;
+LABEL *_STRING__label,*_ARRAY__label;
static LABEL *FILE_label;
@@ -1401,19 +1400,54 @@ static void code_create_arrayC (VOID)
init_a_stack (1);
}
+INSTRUCTION_GRAPH g_create_unboxed_int_array (int n_elements)
+{
+ INSTRUCTION_GRAPH graph_1;
+ int n;
+
+ graph_1=g_create_m (n_elements+3);
+
+ if (_ARRAY__label==NULL)
+ _ARRAY__label=enter_label ("__ARRAY__",IMPORT_LABEL | DATA_LABEL);
+
+ graph_1->instruction_parameters[0].p=g_load_des_i (_ARRAY__label,0);;
+ graph_1->instruction_parameters[1].p=g_load_i (n_elements);
+ graph_1->instruction_parameters[2].p=int_descriptor_graph();
+
+ for (n=0; n<n_elements; ++n)
+ graph_1->instruction_parameters[3+n].p=NULL;
+
+ return graph_1;
+}
+
#define LESS_UNSIGNED(a,b) ((unsigned long)(a)<(unsigned long)(b))
static void code_create_arrayI (VOID)
{
- if (create_arrayI_label==NULL)
- create_arrayI_label=enter_label ("create_arrayI",IMPORT_LABEL);
-
- s_push_b (s_get_b (0));
- s_put_b (1,s_get_b (2));
- s_put_b (2,NULL);
- insert_basic_block (JSR_BLOCK,0,2+1,i_i_vector,create_arrayI_label);
-
- init_a_stack (1);
+ INSTRUCTION_GRAPH graph_1;
+
+ graph_1=s_get_b (0);
+
+ if (graph_1->instruction_code==GLOAD_I && graph_1->instruction_parameters[0].i==0){
+ INSTRUCTION_GRAPH graph_2;
+
+ s_pop_b();
+ s_pop_b();
+
+ graph_2 = g_create_unboxed_int_array (0);
+
+ s_push_a (graph_2);
+ } else {
+ if (create_arrayI_label==NULL)
+ create_arrayI_label=enter_label ("create_arrayI",IMPORT_LABEL);
+
+ s_push_b (graph_1);
+ s_put_b (1,s_get_b (2));
+ s_put_b (2,NULL);
+ insert_basic_block (JSR_BLOCK,0,2+1,i_i_vector,create_arrayI_label);
+
+ init_a_stack (1);
+ }
}
#ifdef G_AI64
@@ -1704,43 +1738,29 @@ void code_create_array_ (char element_descriptor[],int a_size,int b_size)
break;
case 'I':
if (element_descriptor[1]=='N' && element_descriptor[2]=='T' && element_descriptor[3]=='\0'){
-#ifdef ARRAY_OPTIMIZATIONS
INSTRUCTION_GRAPH graph_1;
graph_1=s_get_b (0);
- if (graph_1->instruction_code==GLOAD_I && LESS_UNSIGNED (graph_1->instruction_parameters[0].i,4)){
+
+ if (graph_1->instruction_code==GLOAD_I && LESS_UNSIGNED (graph_1->instruction_parameters[0].i,33)){
INSTRUCTION_GRAPH graph_2;
- int size,n;
- LABEL *__ARRAY___label;
s_pop_b();
- size=graph_1->instruction_parameters[0].i;
-
- graph_2=g_create_m (size+3);
-
- __ARRAY___label=enter_label ("__ARRAY__",IMPORT_LABEL | DATA_LABEL);
- graph_2->instruction_parameters[0].p=g_load_des_i (__ARRAY___label,0);;
- graph_2->instruction_parameters[1].p=g_load_i (size);
- graph_2->instruction_parameters[2].p=int_descriptor_graph();
-
- for (n=0; n<size; ++n)
- graph_2->instruction_parameters[3+n].p=NULL;
+ graph_2 = g_create_unboxed_int_array (graph_1->instruction_parameters[0].i);
s_push_a (graph_2);
- return;
+ } else {
+ if (create_arrayI__label==NULL)
+ create_arrayI__label=enter_label ("_create_arrayI",IMPORT_LABEL);
+
+ s_push_b (graph_1);
+ s_put_b (1,NULL);
+ insert_basic_block (JSR_BLOCK,0,1+1,i_vector,create_arrayI__label);
+
+ init_a_stack (1);
}
-#endif
-
- if (create_arrayI__label==NULL)
- create_arrayI__label=enter_label ("_create_arrayI",IMPORT_LABEL);
-
- s_push_b (s_get_b (0));
- s_put_b (1,NULL);
- insert_basic_block (JSR_BLOCK,0,1+1,i_vector,create_arrayI__label);
-
- init_a_stack (1);
- return;
+ return;
}
break;
case 'P':
@@ -10103,7 +10123,7 @@ void initialize_coding (VOID)
local_labels=NULL;
last_instruction=NULL;
- INT_label=BOOL_label=CHAR_label=REAL_label=FILE_label=_STRING__label=NULL;
+ INT_label=BOOL_label=CHAR_label=REAL_label=FILE_label=_STRING__label=_ARRAY__label=NULL;
halt_label=cat_string_label=NULL;
cmp_string_label=eqD_label=NULL;
diff --git a/cgcode.h b/cgcode.h
index 8b778ca..164668a 100644
--- a/cgcode.h
+++ b/cgcode.h
@@ -31,6 +31,7 @@ extern INSTRUCTION_GRAPH g_fload (int offset,int stack);
extern INSTRUCTION_GRAPH g_instruction_1 (int instruction_code,INSTRUCTION_GRAPH graph_1);
extern INSTRUCTION_GRAPH g_instruction_2 (int instruction_code,INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2);
extern INSTRUCTION_GRAPH g_new_node (int,int,int);
+extern INSTRUCTION_GRAPH g_create_unboxed_int_array (int n_elements);
#ifdef G_A64
# define g_fromf(g1) g_instruction_1(GFROMF,(g1))
diff --git a/cgcodep.h b/cgcodep.h
index 407001d..ac343fe 100644
--- a/cgcodep.h
+++ b/cgcodep.h
@@ -142,6 +142,7 @@ void code_ItoR (VOID);
void code_jmp (char label_name[]);
void code_jmp_ap (int n_args);
void code_jmp_ap_upd (int n_args);
+void code_jmp_not_eqZ (char *integer_string,int integer_string_length,char label_name[]);
void code_jmp_upd (char label_name[]);
void code_jmp_eval (VOID);
void code_jmp_eval_upd (VOID);
@@ -243,6 +244,8 @@ void code_push_node (char *label_name,int n_arguments);
void code_push_node_u (char *label_name,int a_size,int b_size);
void code_push_r_arg_t (VOID);
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);
+void code_pushZ (char *integer_string,int length);
+void code_pushZR (int sign,char *integer_string,int integer_string_length,int exponent);
void code_release (VOID);
void code_randomP (VOID);
void code_replace (char element_descriptor[],int a_size,int b_size);
diff --git a/cginput.c b/cginput.c
index 7457d22..052ed9f 100644
--- a/cginput.c
+++ b/cginput.c
@@ -307,6 +307,169 @@ static int parse_hexadecimal_number (int *n_p)
}
}
+static char *resize_string (char *string,int length,int max_length)
+{
+ if (length==MAX_STRING_LENGTH){
+ char *new_string;
+ int i;
+
+ new_string=malloc (max_length);
+ if (new_string==NULL)
+ error ("Out of memory");
+
+ for (i=0; i<length; ++i)
+ new_string[i]=string[i];
+
+ return new_string;
+ } else {
+ string=realloc (string,max_length);
+ if (string==NULL)
+ error ("Out of memory");
+
+ return string;
+ }
+}
+
+static char *parse_big_integer (char *string,int *string_length_p)
+{
+ int length,max_length;
+
+ length=0;
+ max_length=MAX_STRING_LENGTH;
+
+ if (last_char=='+'){
+ last_char=getc (abc_file);
+ } else if (last_char=='-'){
+ string[length++]=last_char;
+ last_char=getc (abc_file);
+ }
+
+ if (!is_digit_character (last_char))
+ abc_parser_error_i ("Integer expected at line %d\n",line_number);
+
+ do {
+ if (length<max_length)
+ string[length++]=last_char;
+ else {
+ max_length=max_length<<1;
+ string=resize_string (string,length,max_length);
+ string[length++]=last_char;
+ }
+ last_char=getc (abc_file);
+ } while (is_digit_character (last_char));
+
+ if (length>=max_length){
+ ++max_length;
+ string=resize_string (string,length,max_length);
+ }
+
+ string[length]='\0';
+ *string_length_p=length;
+
+ skip_spaces_and_tabs();
+
+ return string;
+}
+
+static char *parse_rational (int *sign_p,char *string,int *string_length_p,int *exponent_p)
+{
+ int n_chars_after_dot,length,max_length,exponent;
+
+ length=0;
+ max_length=MAX_STRING_LENGTH;
+
+ if (last_char=='-'){
+ *sign_p = -1;
+ last_char=getc (abc_file);
+ } else {
+ *sign_p = 0;
+ if (last_char=='+')
+ last_char=getc (abc_file);
+ }
+
+ if (!is_digit_character (last_char))
+ abc_parser_error_i ("Rational expected at line %d\n",line_number);
+
+ do {
+ if (length<max_length)
+ string[length++]=last_char;
+ else {
+ max_length=max_length<<1;
+ string=resize_string (string,length,max_length);
+ string[length++]=last_char;
+ }
+ last_char=getc (abc_file);
+ } while (is_digit_character (last_char));
+
+ if (last_char=='.'){
+ int length_before_dot;
+
+ last_char=getc (abc_file);
+
+ if (!is_digit_character (last_char))
+ abc_parser_error_i ("Digit expected in rational at line %d\n",line_number);
+
+ length_before_dot=length;
+
+ do {
+ if (length<max_length)
+ string[length++]=last_char;
+ else {
+ max_length=max_length<<1;
+ string=resize_string (string,length,max_length);
+ string[length++]=last_char;
+ }
+ last_char=getc (abc_file);
+ } while (is_digit_character (last_char));
+
+ n_chars_after_dot=length-length_before_dot;
+ } else {
+ n_chars_after_dot=0;
+ if (last_char!='e' && last_char!='E')
+ abc_parser_error_i ("'.', 'e' or 'E' expected in rational at line %d\n",line_number);
+ }
+
+ if (length>=max_length){
+ ++max_length;
+ string=resize_string (string,length,max_length);
+ }
+
+ string[length]='\0';
+ *string_length_p=length;
+
+ if (last_char=='e' || last_char=='E'){
+ int exponent_sign;
+
+ last_char=getc (abc_file);
+ if (last_char=='-'){
+ exponent_sign = -1;
+ last_char=getc (abc_file);
+ } else {
+ exponent_sign = 0;
+ if (last_char=='+')
+ last_char=getc (abc_file);
+ }
+
+ if (!is_digit_character (last_char))
+ abc_parser_error_i ("Digit expected in rational at line %d\n",line_number);
+
+ exponent=0;
+ do {
+ exponent=exponent*10+(last_char-'0');
+ last_char=getc (abc_file);
+ } while (is_digit_character (last_char));
+
+ exponent = (exponent ^ exponent_sign) - exponent_sign;
+ } else
+ exponent = 0;
+
+ *exponent_p = exponent - n_chars_after_dot;
+
+ skip_spaces_and_tabs();
+
+ return string;
+}
+
static int parse_0_or_1 (int *integer_p)
{
#if COMPATIBLE_DESC
@@ -712,29 +875,6 @@ static int parse_string (char *string,int *string_length_p)
return 1;
}
-static char *resize_string (char *string,int length,int max_length)
-{
- if (length==MAX_STRING_LENGTH){
- char *new_string;
- int i;
-
- new_string=malloc (max_length);
- if (new_string==NULL)
- error ("Out of memory");
-
- for (i=0; i<length; ++i)
- new_string[i]=string[i];
-
- return new_string;
- } else {
- string=realloc (string,max_length);
- if (string==NULL)
- error ("Out of memory");
-
- return string;
- }
-}
-
static char *parse_string2 (char *string,int *string_length_p)
{
int length,max_length;
@@ -961,6 +1101,55 @@ static int parse_instruction_s2 (InstructionP instruction)
return 1;
}
+static int parse_instruction_z (InstructionP instruction)
+{
+ STRING s;
+ int length;
+ char *integer_string;
+
+ integer_string=parse_big_integer (s,&length);
+
+ instruction->instruction_code_function (integer_string,length);
+
+ if (integer_string!=s)
+ free (integer_string);
+
+ return 1;
+}
+
+static int parse_instruction_zr (InstructionP instruction)
+{
+ STRING s;
+ int length,sign,exponent;
+ char *integer_string;
+
+ integer_string=parse_rational (&sign,s,&length,&exponent);
+
+ instruction->instruction_code_function (sign,integer_string,length,exponent);
+
+ if (integer_string!=s)
+ free (integer_string);
+
+ return 1;
+}
+
+static int parse_instruction_z_a (InstructionP instruction)
+{
+ STRING s,a;
+ int length;
+ char *integer_string;
+
+ integer_string=parse_big_integer (s,&length);
+ parse_label (a);
+
+ instruction->instruction_code_function (integer_string,length,a);
+
+ if (integer_string!=s)
+ free (integer_string);
+
+ return 1;
+}
+
static int parse_instruction_l_s (InstructionP instruction)
{
STRING l1,s1;
@@ -2024,6 +2213,7 @@ static void put_instructions_in_table (void)
put_instruction_name ("jmp_eval", parse_instruction, code_jmp_eval );
put_instruction_name ("jmp_eval_upd", parse_instruction, code_jmp_eval_upd );
put_instruction_name ("jmp_false", parse_instruction_a, code_jmp_false );
+ put_instruction_name ("jmp_not_eqZ", parse_instruction_z_a, code_jmp_not_eqZ );
put_instruction_name ("jmp_true", parse_instruction_a, code_jmp_true );
put_instruction_name ("jsr", parse_instruction_a, code_jsr );
put_instruction_name ("jsr_ap", parse_instruction_n, code_jsr_ap );
@@ -2117,6 +2307,8 @@ static void put_instructions_in_table2 (void)
put_instruction_name ("push_r_arg_t", parse_instruction, code_push_r_arg_t );
put_instruction_name ("push_r_arg_u", parse_instruction_n_n_n_n_n_n_n, code_push_r_arg_u );
put_instruction_name ("push_wl_args", parse_instruction_n_n_n, code_push_args );
+ put_instruction_name ("pushZ", parse_instruction_z, code_pushZ );
+ put_instruction_name ("pushZR", parse_instruction_zr, code_pushZR );
put_instruction_name ("putWL", parse_instruction_n, code_dummy );
put_instruction_name ("randomP", parse_instruction, code_randomP );
put_instruction_name ("release", parse_instruction, code_release );
diff --git a/cginstructions.c b/cginstructions.c
index d9d365e..495f506 100644
--- a/cginstructions.c
+++ b/cginstructions.c
@@ -9,6 +9,7 @@
#if defined (LINUX) && defined (G_AI64)
# include <stdint.h>
#endif
+#include <stdlib.h>
#include "cgport.h"
@@ -1816,6 +1817,906 @@ void code_push_r_arg_u (int a_offset,int a_size,int b_size,int a_arg_offset,int
}
}
+/* convert string to integer */
+
+#ifdef _WIN64
+# define A64
+#endif
+#if defined (__GNUC__) && defined (__SIZEOF_POINTER__)
+# if __SIZEOF_POINTER__==8
+# define A64
+# endif
+#endif
+
+#ifdef _MSC_VER
+# define U_LONG_LONG unsigned __int64
+#else
+# define U_LONG_LONG unsigned long long
+#endif
+
+#ifdef A64
+# define IF_INT_64_OR_32(if64,if32) if64
+# define N_bits_in_int 64
+# define Max_bit_n_in_int 63
+# define N_digits_in_part 27
+# define N_digits_in_part_m1 26
+# define I5PD 7450580596923828125
+# define I2T5PD 14901161193847656250
+# define I1E18 1000000000000000000
+# define IM1E18 (-1000000000000000000)
+#else
+# define IF_INT_64_OR_32(if64,if32) if32
+# define N_bits_in_int 32
+# define Max_bit_n_in_int 31
+# define N_digits_in_part 13
+# define N_digits_in_part_m1 12
+# define I5PD 1220703125
+# define I2T5PD 2441406250
+#endif
+#define I1E9 1000000000
+
+#ifdef A64
+# ifdef __GNUC__
+# define UW unsigned long long
+# define W long long
+# else
+# define UW unsigned __int64
+# define W __int64
+# endif
+#else
+# define UW unsigned int
+# define W int
+#endif
+
+#ifdef _WIN64
+UW _umul128 (UW multiplier, UW multiplicand, UW* highproduct);
+# pragma intrinsic (_umul128)
+#endif
+
+#ifdef A64
+# ifdef __GNUC__
+# define umul_hl(h,l,a,b) \
+ __asm__ ("mulq %3" \
+ : "=a" ((UW)(l)), \
+ "=d" ((UW)(h)) \
+ : "%0" ((UW)(a)), \
+ "rm" ((UW)(b)))
+# else
+# define umul_hl(h,l,a,b) l=_umul128 (a,b,&h)
+# endif
+#endif
+
+struct integer {
+ W s;
+ UW *a;
+};
+
+static UW convertchars (int i,int end_i,char s[])
+{
+ UW n;
+
+ n=0;
+ while (i<end_i){
+ n=n*10+(s[i]-48);
+ i=i+1;
+ }
+ return n;
+}
+
+static UW convert9c (int i,char s[])
+{
+ UW n;
+
+ n=s[i]-48;
+ n=n*10+(s[i+1]-48);
+ n=n*10+(s[i+2]-48);
+ n=n*10+(s[i+3]-48);
+ n=n*10+(s[i+4]-48);
+ n=n*10+(s[i+5]-48);
+ n=n*10+(s[i+6]-48);
+ n=n*10+(s[i+7]-48);
+ n=n*10+(s[i+8]-48);
+
+ return n;
+}
+
+#ifdef A64
+UW
+#else
+static U_LONG_LONG
+#endif
+ convert10to13c (int n_chars,char s[])
+{
+ int i;
+ UW nl,nh;
+#ifndef A64
+ U_LONG_LONG hl;
+#endif
+
+ i = n_chars-9;
+ nl = convert9c (i,s);
+ nh = convertchars (0,i,s);
+#ifdef A64
+ return nh*I1E9+nl;
+#else
+ hl = ((U_LONG_LONG)nh)*((U_LONG_LONG)I1E9);
+
+ return hl+nl;
+#endif
+}
+
+#ifndef A64
+static U_LONG_LONG convert13c_32 (int i,char s[])
+{
+ UW nl,nh;
+ U_LONG_LONG hl;
+
+ nl=convert9c (i+4,s);
+
+ nh=s[i]-48;
+ nh=nh*10+(s[i+1]-48);
+ nh=nh*10+(s[i+2]-48);
+ nh=nh*10+(s[i+3]-48);
+
+ hl = ((U_LONG_LONG)nh)*((U_LONG_LONG)I1E9);
+ return hl+nl;
+}
+#endif
+
+#ifdef A64
+static UW convert18c_64 (int i,char s[])
+{
+ UW t48,n;
+
+ t48 = 0x3000000030;
+ n=(((UW)s[i]<<32)+s[i+9])-t48;
+ n=n*10+((((UW)s[i+1]<<32)+s[i+10])-t48);
+ n=n*10+((((UW)s[i+2]<<32)+s[i+11])-t48);
+ n=n*10+((((UW)s[i+3]<<32)+s[i+12])-t48);
+ n=n*10+((((UW)s[i+4]<<32)+s[i+13])-t48);
+ n=n*10+((((UW)s[i+5]<<32)+s[i+14])-t48);
+ n=n*10+((((UW)s[i+6]<<32)+s[i+15])-t48);
+ n=n*10+((((UW)s[i+7]<<32)+s[i+16])-t48);
+ n=n*10+((((UW)s[i+8]<<32)+s[i+17])-t48);
+ return (n>>32) * I1E9 + (n & 0xffffffff);
+}
+
+static UW convert19to27c_64 (int n_chars,char *s,UW *h_p)
+{
+ int i;
+ UW nh,nl,h,l;
+
+ i = n_chars-18;
+ nl = convert18c_64 (i,s);
+ nh = convertchars (0,i,s);
+
+ umul_hl (h,l,nh,I1E18);
+ l = l+nl;
+ *h_p = h+(l<nl);
+ return l;
+}
+
+static UW convert27c_64 (int i,char s[],UW *h_p)
+{
+ UW nh,nl,h,l;
+
+ nl=convert18c_64 (i+9,s);
+ nh=convert9c (i,s);
+
+ umul_hl (h,l,nh,I1E18);
+ l = l+nl;
+ *h_p = h+(l<nl);
+ return l;
+}
+#endif
+
+static int convert_first_chars (int n_chars_in_first_part,char s[],int i_a_f,UW a[])
+{
+ if (n_chars_in_first_part==0)
+ return i_a_f;
+
+ if (n_chars_in_first_part<IF_INT_64_OR_32 (19,10)){
+ UW n;
+
+ n = convertchars (0,n_chars_in_first_part,s);
+ a[i_a_f]=n;
+ return i_a_f+1;
+ } else {
+ UW h,l;
+#ifdef A64
+ l = convert19to27c_64 (n_chars_in_first_part,s,&h);
+#else
+ U_LONG_LONG hl;
+
+ hl = convert10to13c (n_chars_in_first_part,s);
+ h=(UW)(hl>>N_bits_in_int);
+ l=(UW)hl;
+#endif
+ a[i_a_f]=l;
+ if (h==0)
+ return i_a_f+1;
+ else {
+ a[i_a_f+1]=h;
+ return i_a_f+2;
+ }
+ }
+}
+
+static int mul_5pd_add (int i,int i_a,UW a[])
+{
+ UW n;
+
+ n=0;
+
+ while (i!=i_a){
+ UW ai;
+#ifdef A64
+ UW h,l;
+#else
+ U_LONG_LONG hl;
+#endif
+ ai=a[i];
+#ifdef A64
+ umul_hl (h,l,ai,I5PD);
+ l=l+n;
+ h=h+(l<n);
+ a[i]=l;
+ n=h;
+#else
+ hl=((U_LONG_LONG)ai)*((U_LONG_LONG)I5PD);
+ hl=hl+n;
+ a[i]=(unsigned int)hl;
+ n=(unsigned int)(hl>>32);
+#endif
+ ++i;
+ }
+
+ if (n!=0){
+ a[i]=n;
+ return i+1;
+ } else
+ return i;
+}
+
+static int addi (UW n,int i_a_f,int i_a_e,UW a[])
+{
+ UW s;
+
+ if (i_a_f==i_a_e){
+ a[i_a_f]=n;
+ return i_a_f+1;
+ }
+ s=a[i_a_f]+n;
+ a[i_a_f]=s;
+ if (s<n){ /* carry */
+ int i;
+
+ i=i_a_f+1;
+ while (i<i_a_e){
+ UW ai;
+
+ ai=a[i]+1;
+ a[i]=ai;
+ if (ai!=0)
+ return i_a_e;
+ i=i+1;
+ }
+ a[i]=1;
+ return i_a_e+1;
+ }
+ return i_a_e;
+}
+
+static int shift_left (int i,UW n,int shift,int i_a,UW a[])
+{
+ while (i<i_a){
+ UW ai,new_n;
+
+ ai=a[i];
+ new_n = ai>>(N_bits_in_int-shift);
+ ai = (ai<<shift)+n;
+ a[i]=ai;
+ i=i+1;
+ n = new_n;
+ }
+
+ if (n==0)
+ return i_a;
+ else
+ a[i_a]=n;
+ return i_a+1;
+}
+
+static void stoi_next_parts (int i_s,char s[],int size_s,int i_a_f,int i_a_e,int shift,UW r,UW a[],int size_a)
+{
+ while (i_s<size_s){
+#ifdef A64
+ UW h,l,yh,yl;
+#else
+ U_LONG_LONG hl,yhl;
+#endif
+
+#ifdef A64
+ l = convert27c_64 (i_s,s,&h);
+ umul_hl (yh,yl,r,I5PD);
+#else
+ hl = convert13c_32 (i_s,s);
+ yhl = ((U_LONG_LONG)r)*((U_LONG_LONG)I5PD);
+#endif
+ if (shift<IF_INT_64_OR_32 (37,19)){
+ UW x,new_r,n;
+#ifdef A64
+ UW rh,rl;
+
+ x = l & 0x7ffffff;
+ l = (l>>N_digits_in_part)+(h<<37);
+
+ rl = yl+l;
+ rh = yh+(rl<yl);
+ new_r = x | ((rl & ((((UW)1)<<shift)-1))<<N_digits_in_part);
+ n = (rl>>shift)+(rh<<(N_bits_in_int-shift));
+#else
+ UW l;
+ U_LONG_LONG rhl;
+
+ x = (UW)hl & 0x1fff;
+ l = (UW)(hl>>N_digits_in_part);
+ rhl = yhl+l;
+ new_r = x | ((((UW)rhl) & ((((UW)1)<<shift)-1))<<N_digits_in_part);
+ n = (UW)(rhl>>shift);
+#endif
+
+ i_a_e = mul_5pd_add (i_a_f,i_a_e,a);
+ i_a_e = addi (n,i_a_f,i_a_e,a);
+ shift += N_digits_in_part;
+ r = new_r;
+ } else if (shift==IF_INT_64_OR_32 (37,19)){
+#ifdef A64
+ yh =(yh<<N_digits_in_part) + (yl>>IF_INT_64_OR_32 (37,19));
+ yl = yl<<N_digits_in_part;
+ l=l+yl;
+ h=h+yh+(l<yl);
+#else
+ yhl = yhl<<N_digits_in_part;
+ hl = yhl + hl;
+#endif
+ i_a_e = mul_5pd_add (i_a_f,i_a_e,a);
+ i_a_e = addi (IF_INT_64_OR_32 (h,(UW)(hl>>32)),i_a_f,i_a_e,a);
+
+ if (i_a_f<=0)
+ printf ("error in stoi_next_parts\n");
+
+ i_a_f = i_a_f-1;
+ a[i_a_f]=IF_INT_64_OR_32 (l,(UW)hl);
+
+ shift = 0;
+ r = 0;
+ } else {
+ UW new_r;
+ int n,ys;
+
+ n = shift-IF_INT_64_OR_32 (37,19);
+ new_r = (IF_INT_64_OR_32 (l,(UW)hl)) & ((((UW)1)<<n)-1);
+#ifdef A64
+ l =(l>>n) + (h<<(N_bits_in_int-n));
+ h = h>>n;
+#else
+ hl = hl>>n;
+#endif
+ ys = N_digits_in_part-n;
+#ifdef A64
+ yh =(yh<<ys) + (yl>>(N_bits_in_int-ys));
+ yl = yl<<ys;
+ l=l+yl;
+ h=h+yh+(l<yl);
+#else
+ yhl = yhl << ys;
+ hl = yhl+hl;
+#endif
+ i_a_e = mul_5pd_add (i_a_f,i_a_e,a);
+ i_a_e = addi (IF_INT_64_OR_32 (h,(UW)(hl>>32)),i_a_f,i_a_e,a);
+
+ if (i_a_f<=0)
+ printf ("error in stoi_next_parts\n");
+ i_a_f = i_a_f-1;
+ a[i_a_f]=IF_INT_64_OR_32 (l,(UW)hl);
+
+ shift = n;
+ r = new_r;
+ }
+ i_s += N_digits_in_part;
+ }
+
+ if (i_s==size_s && i_a_f==0 && i_a_e<=size_a){
+ if (shift!=0)
+ i_a_e=shift_left (0,r,shift,i_a_e,a);
+ return;
+ } else
+ printf ("error in stoi_next_parts\n");
+}
+
+static struct integer string_to_integer (W sign,char *s,int size_s)
+{
+ if (s[0]=='-'){
+ sign=-1;
+ --size_s;
+ ++s;
+ }
+
+ if (size_s<=N_digits_in_part){
+ if (size_s<IF_INT_64_OR_32 (19,10)){
+ struct integer i;
+
+ i.s=(convertchars (0,size_s,s) ^ sign)-sign;
+ i.a=NULL;
+
+ return i;
+ } else {
+ UW h,l;
+
+#ifdef A64
+ l = convert19to27c_64 (size_s,s,&h);
+#else
+ U_LONG_LONG hl;
+
+ hl = convert10to13c (size_s,s);
+ h=(UW)(hl>>N_bits_in_int);
+ l=(UW)hl;
+#endif
+
+ if (h==0){
+ struct integer i;
+
+ if ((UW)l < (UW)(((UW)1<<(UW)Max_bit_n_in_int)-sign)){
+ i.s=(l ^ sign)-sign;
+ i.a=NULL;
+
+ return i;
+ } else {
+ UW *a;
+
+ a=calloc (2,sizeof (UW));
+ if (a==NULL)
+ error ("Out of memory\n");
+
+ a[0]=1;
+ a[1]=l;
+
+ i.s=sign;
+ i.a=a+1;
+
+ return i;
+ }
+ } else {
+ struct integer i;
+ UW *a;
+
+ a=calloc (3,sizeof (UW));
+ if (a==NULL)
+ error ("Out of memory\n");
+
+ a[0]=2;
+ a[1]=l;
+ a[2]=h;
+
+ i.s=sign;
+ i.a=a+1;
+
+ return i;
+ }
+ }
+ } else {
+ int n_chars,n_parts,n_chars_in_parts,n_chars_in_first_part,n_shifts,size_a,i_a_f,i_a_e,i;
+ UW *a;
+
+ n_chars = size_s;
+ n_parts = n_chars/N_digits_in_part;
+ n_chars_in_parts = n_parts * N_digits_in_part;
+ n_chars_in_first_part = n_chars-n_chars_in_parts;
+ n_shifts = n_chars_in_parts>>IF_INT_64_OR_32(6,5);
+ size_a = n_parts + 3 + n_shifts;
+
+ a = calloc (size_a+1,sizeof(UW));
+ if (a==NULL)
+ printf ("Out of memory\n");
+ ++a;
+
+ i_a_f = n_shifts;
+ i_a_e = convert_first_chars (n_chars_in_first_part,s,i_a_f,a);
+
+ stoi_next_parts (n_chars_in_first_part,s,size_s,i_a_f,i_a_e,0,0,a,size_a);
+
+ i=size_a-1;
+ while (i!=0 && a[i]==0)
+ --i;
+
+ if (i==0 && (UW)a[0] < (UW)(((UW)1<<(UW)Max_bit_n_in_int)-sign)){
+ struct integer si;
+
+ si.a=NULL;
+ si.s=(a[0] ^ sign)-sign;
+
+ free (a-1);
+
+ return si;
+ } else if (i+1==size_a){
+ struct integer si;
+
+ si.a=a;
+ si.s=sign;
+ a[-1]=i+1;
+
+ return si;
+ } else {
+ struct integer si;
+
+ a=1+(UW*)realloc (a-1,sizeof (UW)*(i+1+1));
+ if (a==0)
+ printf ("realloc failed\n");
+
+ a[-1]=i+1;
+
+ si.a=a;
+ si.s=sign;
+
+ return si;
+ }
+ }
+}
+
+#define g_cmp_eq(g1,g2) g_instruction_2(GCMP_EQ,(g1),(g2))
+
+void code_jmp_not_eqZ (char *integer_string,int integer_string_length,char label_name[])
+{
+ struct integer integer;
+ INSTRUCTION_GRAPH graph_1,graph_2,graph_3,graph_4;
+
+ integer=string_to_integer (0,integer_string,integer_string_length);
+
+ if (integer.a==NULL){
+ graph_1=s_get_b (0);
+ graph_2=g_load_i (integer.s);
+ graph_3=g_cmp_eq (graph_2,graph_1);
+ s_push_b (graph_3);
+ code_jmp_false (label_name);
+
+ graph_1=s_get_a (0);
+ graph_2=g_load_id (STACK_ELEMENT_SIZE,graph_1);
+ graph_3=g_load_i (0);
+ graph_4=g_cmp_eq (graph_3,graph_2);
+ s_push_b (graph_4);
+ code_jmp_false (label_name);
+ } else {
+ int i,integer_size;
+
+ integer_size=integer.a[-1];
+
+ graph_1=s_get_a (0);
+ graph_2=g_load_id (STACK_ELEMENT_SIZE,graph_1);
+ graph_3=g_load_i (integer_size);
+ graph_4=g_cmp_eq (graph_3,graph_2);
+ s_push_b (graph_4);
+ code_jmp_false (label_name);
+
+ for (i=0; i<integer_size; ++i){
+ graph_1=s_get_a (0);
+ graph_2=g_load_id ((i+2)<<STACK_ELEMENT_LOG_SIZE,graph_1);
+ graph_3=g_load_i (integer.a[i]);
+ graph_4=g_cmp_eq (graph_3,graph_2);
+ s_push_b (graph_4);
+ code_jmp_false (label_name);
+ }
+
+ graph_1=s_get_b (0);
+ graph_2=g_load_i (integer.s);
+ graph_3=g_cmp_eq (graph_2,graph_1);
+ s_push_b (graph_3);
+ code_jmp_false (label_name);
+ }
+}
+
+void code_pushZ (char *integer_string,int integer_string_length)
+{
+ struct integer integer;
+ INSTRUCTION_GRAPH graph_1,graph_2;
+
+ integer=string_to_integer (0,integer_string,integer_string_length);
+
+ graph_1=g_load_i (integer.s);
+ if (integer.a==NULL)
+ graph_2=g_create_unboxed_int_array (0);
+ else {
+ int i,n_elements;
+
+ n_elements=integer.a[-1];
+ graph_2=g_create_unboxed_int_array (n_elements);
+ for (i=0; i<n_elements; ++i)
+ graph_2->instruction_parameters[3+i].p=g_load_i (integer.a[i]);
+ }
+
+ s_push_b (graph_1);
+ s_push_a (graph_2);
+}
+
+static struct integer shift_right (struct integer n,unsigned int n_bits)
+{
+ UW *a;
+
+ a=n.a;
+ if (a==NULL)
+ n.s = n.s>>n_bits;
+ else {
+ UW previous_e;
+ int i,n_n_elements;
+
+ n_n_elements=a[-1];
+
+ previous_e=0;
+ for (i=n_n_elements-1; i>=0; --i){
+ UW e;
+
+ e = a[i];
+ a[i] = (e>>n_bits) + (previous_e<<(N_bits_in_int-n_bits));
+ previous_e = e;
+ }
+
+ if (a[n_n_elements-1]==0){
+ --n_n_elements;
+ a[-1]=n_n_elements;
+ }
+
+ if (n_n_elements==1 && (W)a[0]>=0){
+ n.s=a[0];
+ n.a=NULL;
+ }
+ }
+
+ return n;
+}
+
+static int divisible_by_5 (struct integer n)
+{
+ UW s;
+
+ if (n.a==NULL)
+ s=n.s;
+ else {
+ UW *a;
+ int i,n_elements;
+
+ a=n.a;
+ n_elements=a[-1];
+
+ s=0;
+ for (i=0; ; ){
+ int end_i;
+
+ end_i=i+10000;
+ if (end_i>n_elements)
+ end_i=n_elements;
+
+ while (i<end_i){
+ UW e;
+
+ e=a[i];
+ s+=IF_INT_64_OR_32 ((e & 0xffffffffu)+(e>>32u),(e & 0xffffu)+(e>>16u));
+ ++i;
+ }
+
+ if (i>=n_elements)
+ break;
+
+ s = s % 5;
+ }
+ }
+
+ return s % 5==0;
+}
+
+static struct integer exact_div_5 (struct integer n)
+{
+ if (n.a==NULL)
+ n.s=n.s / 5;
+ else {
+ int i,n_elements;
+ UW borrow,*a;
+
+ a=n.a;
+ n_elements=a[-1];
+
+ borrow=0;
+ for (i=0; i<n_elements; ++i){
+ UW ai,e,ed5,h;
+
+ ai=a[i];
+
+ e=ai-borrow;
+ borrow = e>ai;
+
+ ed5=e * IF_INT_64_OR_32 (0xcccccccccccccccd,0xcccccccd);
+
+ h = (ed5 + (ed5<<2u)) < ed5;
+ borrow += h;
+ borrow += ed5>>IF_INT_64_OR_32 (62u,30u);
+
+ a[i]=ed5;
+ }
+
+ if (a[n_elements-1]==0){
+ --n_elements;
+ a[-1]=n_elements;
+ }
+
+ if (n_elements==1 && (W)a[0]>=0){
+ n.s=a[0];
+ n.a=NULL;
+ }
+ }
+
+ return n;
+}
+
+void code_pushZR (int sign,char *integer_string,int integer_string_length,int exponent)
+{
+ struct integer numerator,denominator;
+ INSTRUCTION_GRAPH graph_1,graph_2,graph_3,graph_4;
+ char *numerator_string;
+ int denominator_string_length;
+
+ while (integer_string[0]=='0' && integer_string_length>1){
+ ++integer_string;
+ --integer_string_length;
+ }
+
+ while (exponent<0 && integer_string_length>1 && integer_string[integer_string_length-1]=='0'){
+ --integer_string_length;
+ ++exponent;
+ }
+
+ if (integer_string_length==1 && integer_string[0]=='0')
+ exponent=0;
+
+ if (exponent>0){
+ int i,new_string_length;
+
+ new_string_length=integer_string_length+exponent;
+ numerator_string=memory_allocate (new_string_length+1);
+
+ for (i=0; i<integer_string_length; ++i)
+ numerator_string[i]=integer_string[i];
+ for ( ; i<new_string_length; ++i)
+ numerator_string[i]='0';
+ numerator_string[i]='\0';
+
+ integer_string=numerator_string;
+ integer_string_length=new_string_length;
+ } else
+ numerator_string=NULL;
+
+ numerator=string_to_integer (sign,integer_string,integer_string_length);
+
+ if (numerator_string!=NULL){
+ memory_free (numerator_string);
+ numerator_string=NULL;
+ }
+
+ if (exponent<0){
+ char *denominator_string;
+ int i,exponent2,exponent5;
+
+ denominator_string_length=1-exponent;
+ denominator_string=memory_allocate (denominator_string_length+1);
+
+ denominator_string[0]='1';
+ for (i=1; i<denominator_string_length; ++i)
+ denominator_string[i]='0';
+ denominator_string[i]='\0';
+
+ denominator=string_to_integer (0,denominator_string,denominator_string_length);
+
+ memory_free (denominator_string);
+
+ exponent2=-exponent;
+ exponent5=exponent2;
+
+ if (exponent2>=N_bits_in_int && numerator.a!=NULL){
+ int n_n_elements,n_d_elements;
+ UW *n_a,*d_a;
+
+ n_a=numerator.a;
+ n_n_elements=n_a[-1];
+
+ d_a=denominator.a;
+ n_d_elements=d_a[-1];
+
+ while (exponent2>=N_bits_in_int && n_a[0]==0){
+ --n_n_elements;
+ ++n_a;
+
+ --n_d_elements;
+ ++d_a;
+
+ exponent2-=N_bits_in_int;
+ }
+
+ if (n_n_elements==1 && (W)n_a[0]>=0){
+ numerator.s=n_a[0];
+ numerator.a=NULL;
+ } else {
+ numerator.a=n_a;
+ n_a[-1]=n_n_elements;
+ }
+
+ /* >= 32 bits, because >= 5^32 */
+ denominator.a=d_a;
+ d_a[-1]=n_d_elements;
+ }
+
+ if (exponent2>0){
+ UW n0;
+
+ if (numerator.a==NULL)
+ n0=numerator.s;
+ else
+ n0=numerator.a[0];
+
+ if ((n0 & 1)==0){
+ unsigned int n_0_bits,max_bits;
+
+ n0=n0>>1;
+ n_0_bits=1;
+ while (n_0_bits<exponent2 && (n0 & 1)==0){
+ n0=n0>>1;
+ ++n_0_bits;
+ }
+
+ exponent2-=n_0_bits;
+
+ numerator = shift_right (numerator,n_0_bits);
+ denominator = shift_right (denominator,n_0_bits);
+ }
+ }
+
+ while (exponent5>0 && divisible_by_5 (numerator)){
+ numerator = exact_div_5 (numerator);
+ denominator = exact_div_5 (denominator);
+ --exponent5;
+ }
+ } else {
+ denominator.s=1;
+ denominator.a=NULL;
+ }
+
+ graph_1=g_load_i (numerator.s);
+ if (numerator.a==NULL)
+ graph_2=g_create_unboxed_int_array (0);
+ else {
+ int i,n_elements;
+
+ n_elements=numerator.a[-1];
+ graph_2=g_create_unboxed_int_array (n_elements);
+ for (i=0; i<n_elements; ++i)
+ graph_2->instruction_parameters[3+i].p=g_load_i (numerator.a[i]);
+ }
+
+ graph_3=g_load_i (denominator.s);
+ if (denominator.a==NULL)
+ graph_4=g_create_unboxed_int_array (0);
+ else {
+ int i,n_elements;
+
+ n_elements=denominator.a[-1];
+ graph_4=g_create_unboxed_int_array (n_elements);
+ for (i=0; i<n_elements; ++i)
+ graph_4->instruction_parameters[3+i].p=g_load_i (denominator.a[i]);
+ }
+
+ s_push_b (graph_3);
+ s_push_a (graph_4);
+ s_push_b (graph_1);
+ s_push_a (graph_2);
+}
+
extern int profile_flag;
extern LABEL *profile_function_label;