diff options
-rw-r--r-- | cgaas.c | 60 | ||||
-rw-r--r-- | cgawas.c | 70 |
2 files changed, 128 insertions, 2 deletions
@@ -3549,7 +3549,7 @@ static void as_dyadic_float_instruction (struct instruction *instruction,int cod LABEL *sign_real_mask_label; -static void as_float_neg_instruction (struct instruction *instruction,int code) +static void as_float_neg_instruction (struct instruction *instruction) { int d_freg; @@ -3600,6 +3600,59 @@ static void as_float_neg_instruction (struct instruction *instruction,int code) as_f_a (0x66,0x57,sign_real_mask_label,d_freg); /* xorpd */ } +LABEL *abs_real_mask_label; + +static void as_float_abs_instruction (struct instruction *instruction) +{ + int d_freg; + + d_freg=instruction->instruction_parameters[1].parameter_data.reg.r; + + switch (instruction->instruction_parameters[0].parameter_type){ + case P_F_REGISTER: + if (instruction->instruction_parameters[0].parameter_data.reg.r!=d_freg) + as_f_r (0xf2,0x10,instruction->instruction_parameters[0].parameter_data.reg.r,d_freg); + break; + case P_INDIRECT: + as_f_id (0x66,0x12,instruction->instruction_parameters[0].parameter_offset, + instruction->instruction_parameters[0].parameter_data.reg.r,d_freg); + break; + case P_INDEXED: + as_f_x (0x66,0x12,instruction->instruction_parameters[0].parameter_offset, + instruction->instruction_parameters[0].parameter_data.ir,d_freg); + break; + case P_F_IMMEDIATE: + as_f_i (0x66,0x12,instruction->instruction_parameters[0].parameter_data.r,d_freg); + break; + default: + internal_error_in_function ("as_float_abs_instruction"); + return; + } + + if (abs_real_mask_label==NULL){ + LABEL *new_label; + + new_label=allocate_memory_from_heap (sizeof (struct label)); + + new_label->label_flags=DATA_LABEL; + + if (data_object_label->object_section_align<4) + data_object_label->object_section_align=4; + while ((data_buffer_p-current_data_buffer->data-data_object_label->object_label_offset) & 0xc) + store_long_word_in_data_section (0); + + define_data_label (new_label); + store_long_word_in_data_section (0xffffffff); + store_long_word_in_data_section (0x7fffffff); + store_long_word_in_data_section (0xffffffff); + store_long_word_in_data_section (0x7fffffff); + + abs_real_mask_label=new_label; + } + + as_f_a (0x66,0x54,abs_real_mask_label,d_freg); /* andpd */ +} + static void as_float_branch_instruction (struct instruction *instruction,int n) { struct label *new_label; @@ -4144,7 +4197,10 @@ static void as_instructions (struct instruction *instruction) as_dyadic_float_instruction (instruction,0xf2,0x51); break; case IFNEG: - as_float_neg_instruction (instruction,0xe0); + as_float_neg_instruction (instruction); + break; + case IFABS: + as_float_abs_instruction (instruction); break; case IFSEQ: as_set_float_condition_instruction (instruction,0); @@ -2716,6 +2716,73 @@ static void w_as_float_neg_instruction (struct instruction *instruction) w_as_newline(); } +static int abs_real_mask_imported=0; + +static void w_as_float_abs_instruction (struct instruction *instruction) +{ + int d_freg; + + d_freg=instruction->instruction_parameters[1].parameter_data.reg.r; + + switch (instruction->instruction_parameters[0].parameter_type){ + case P_F_IMMEDIATE: + { + int label_number=next_label_id++; + + w_as_float_constant (label_number,instruction->instruction_parameters[0].parameter_data.r); + + w_as_opcode ("movlpd"); + w_as_fp_register (d_freg); + w_as_comma(); + fprintf (assembly_file,"qword ptr i_%d",label_number); + w_as_newline(); + break; + } + case P_INDIRECT: + w_as_opcode ("movlpd"); + w_as_fp_register (d_freg); + w_as_comma(); + fprintf (assembly_file,"qword ptr "); + w_as_indirect (instruction->instruction_parameters[0].parameter_offset,instruction->instruction_parameters[0].parameter_data.reg.r); + w_as_newline(); + break; + case P_INDEXED: + w_as_opcode ("movlpd"); + w_as_fp_register (d_freg); + w_as_comma(); + fprintf (assembly_file,"qword ptr "); + w_as_indexed (instruction->instruction_parameters[0].parameter_offset,instruction->instruction_parameters[0].parameter_data.ir); + w_as_newline(); + break; + case P_F_REGISTER: + if (instruction->instruction_parameters[0].parameter_data.reg.r!=d_freg){ + w_as_opcode ("movsd"); + w_as_fp_register (d_freg); + w_as_comma(); + w_as_fp_register (instruction->instruction_parameters[0].parameter_data.reg.r); + w_as_newline(); + } + break; + default: + internal_error_in_function ("w_as_float_abs_instruction"); + return; + } + + if (!abs_real_mask_imported){ + w_as_opcode ("extrn"); + fprintf (assembly_file,"abs_real_mask:near"); + w_as_newline(); + + abs_real_mask_imported=1; + } + + w_as_opcode ("andpd"); + w_as_fp_register (d_freg); + w_as_comma(); + fprintf (assembly_file,"oword ptr abs_real_mask"); + w_as_newline(); +} + static void w_as_fmove_instruction (struct instruction *instruction) { switch (instruction->instruction_parameters[1].parameter_type){ @@ -3105,6 +3172,9 @@ static void w_as_instructions (register struct instruction *instruction) case IFNEG: w_as_float_neg_instruction (instruction); break; + case IFABS: + w_as_float_abs_instruction (instruction); + break; case IFSEQ: w_as_set_float_condition_instruction (instruction,0); break; |