summaryrefslogtreecommitdiff
path: root/cgarmwas.c
diff options
context:
space:
mode:
authorJohn van Groningen2015-09-01 12:41:20 +0000
committerJohn van Groningen2015-09-01 12:41:20 +0000
commitfd56a2efc3868481a2a94db80c90fd0a5895c780 (patch)
tree7b0956cb3abe547388cd5e90c3accac8510dadbf /cgarmwas.c
parentinitialize order_mode field for GBEFORE and GBEFORE0 nodes (diff)
Diffstat (limited to 'cgarmwas.c')
-rw-r--r--cgarmwas.c2856
1 files changed, 2856 insertions, 0 deletions
diff --git a/cgarmwas.c b/cgarmwas.c
new file mode 100644
index 0000000..435fab4
--- /dev/null
+++ b/cgarmwas.c
@@ -0,0 +1,2856 @@
+/*
+ File: cgarmwas.c
+ Author: John van Groningen
+ Machine: ARM
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+#include "cgport.h"
+#include "cgrconst.h"
+#include "cgtypes.h"
+#include "cg.h"
+#include "cgiconst.h"
+#include "cgcode.h"
+#include "cginstructions.h"
+#include "cgarmas.h"
+#include "cgarmwas.h"
+
+#define for_l(v,l,n) for(v=(l);v!=NULL;v=v->n)
+
+#define IO_BUF_SIZE 8192
+
+static FILE *assembly_file;
+
+static void w_as_newline (VOID)
+{
+ putc ('\n',assembly_file);
+}
+
+static void w_as_opcode (char *opcode)
+{
+ fprintf (assembly_file,"\t%s\t",opcode);
+}
+
+static void w_as_instruction_without_parameters (char *opcode)
+{
+ fprintf (assembly_file,"\t%s\n",opcode);
+}
+
+static void w_as_define_local_label (int label_number)
+{
+ fprintf (assembly_file,"l_%d:\n",label_number);
+}
+
+static void w_as_define_local_data_label (int label_number)
+{
+ fprintf (assembly_file,"l_%d:\n",label_number);
+}
+
+static void w_as_define_internal_label (int label_number)
+{
+ fprintf (assembly_file,"i_%d:\n",label_number);
+}
+
+static void w_as_define_internal_data_label (int label_number)
+{
+ fprintf (assembly_file,"i_%d:\n",label_number);
+}
+
+void w_as_internal_label_value (int label_id)
+{
+ fprintf (assembly_file,"\t.long\ti_%d\n",label_id);
+}
+
+static int in_data_section;
+
+#ifdef FUNCTION_LEVEL_LINKING
+void w_as_new_data_module (void)
+{
+}
+#endif
+
+void w_as_to_data_section (VOID)
+{
+ if (!in_data_section){
+ in_data_section=1;
+ w_as_instruction_without_parameters (".data");
+ }
+}
+
+#ifdef DATA_IN_CODE_SECTION
+# define w_as_to_data_section w_as_to_code_section
+#endif
+
+static void w_as_to_code_section (VOID)
+{
+ if (in_data_section){
+ in_data_section=0;
+ w_as_instruction_without_parameters (".text");
+ }
+}
+
+static void w_as_align (int i)
+{
+ fprintf (assembly_file,"\t.p2align\t%d\n",i);
+}
+
+static void w_as_space (int i)
+{
+ fprintf (assembly_file,"\t.space\t%d\n",i);
+}
+
+void w_as_word_in_data_section (int n)
+{
+ w_as_to_data_section();
+ w_as_opcode (".hword");
+ fprintf (assembly_file,"%d",n);
+ w_as_newline();
+}
+
+void w_as_long_in_data_section (int n)
+{
+#ifdef DATA_IN_CODE_SECTION
+ if (!in_data_section){
+ in_data_section=1;
+ w_as_instruction_without_parameters (".data");
+ }
+#else
+ w_as_to_data_section();
+#endif
+ w_as_opcode (".long");
+ fprintf (assembly_file,"%d",n);
+ w_as_newline();
+}
+
+void w_as_label_in_data_section (char *label_name)
+{
+ w_as_to_data_section ();
+ fprintf (assembly_file,"\t.long\t%s\n",label_name);
+}
+
+static void w_as_label_in_code_section (char *label_name)
+{
+ w_as_to_code_section ();
+ fprintf (assembly_file,"\t.long\t%s\n",label_name);
+}
+
+void w_as_descriptor_in_data_section (char *label_name)
+{
+ w_as_to_data_section();
+ w_as_align (2);
+ fprintf (assembly_file,"\t.long\t%s+2\n",label_name);
+}
+
+#define MAX_BYTES_PER_LINE 16
+
+static int w_as_data (int n,char *data,int length)
+{
+ int i,in_string;
+
+ in_string=0;
+
+ for (i=0; i<length; ++i){
+ int c;
+
+ if (n>=MAX_BYTES_PER_LINE){
+ if (in_string){
+ putc ('\"',assembly_file);
+ in_string=0;
+ }
+ w_as_newline();
+ n=0;
+ }
+
+ c=((unsigned char*)data)[i];
+ if (isalnum (c) || c=='_' || c==' '){
+ if (!in_string){
+ if (n!=0)
+ w_as_newline();
+ w_as_opcode (".ascii");
+ putc ('\"',assembly_file);
+ in_string=1;
+ n=0;
+ }
+ putc (c,assembly_file);
+ } else {
+ if (n==0)
+ w_as_opcode (".byte");
+ else {
+ if (in_string){
+ putc ('\"',assembly_file);
+ w_as_newline();
+ w_as_opcode (".byte");
+ in_string=0;
+ n=0;
+ } else
+ putc (',',assembly_file);
+ }
+
+ fprintf (assembly_file,"0x%02x",c);
+ }
+ ++n;
+ }
+
+ if (in_string){
+ putc ('\"',assembly_file);
+ w_as_newline();
+ return 0;
+ } else
+ return n;
+}
+
+static int w_as_zeros (register int n,register int length)
+{
+ register int i;
+
+ for (i=0; i<length; ++i){
+ if (n>=MAX_BYTES_PER_LINE){
+ w_as_newline();
+ n=0;
+ }
+ if (n==0)
+ w_as_opcode (".byte");
+ else
+ putc (',',assembly_file);
+ fprintf (assembly_file,"0");
+ ++n;
+ }
+ return n;
+}
+
+void w_as_define_data_label (int label_number)
+{
+ w_as_to_data_section();
+
+ w_as_define_local_data_label (label_number);
+}
+
+void w_as_labeled_c_string_in_data_section (char *string,int length,int label_number)
+{
+ int n;
+
+ w_as_to_data_section();
+
+ w_as_define_local_data_label (label_number);
+
+ n=w_as_data (0,string,length);
+ if (length & 3)
+ n=w_as_zeros (n,4-(length & 3));
+ else
+ n=w_as_zeros (n,4);
+ if (n>0)
+ w_as_newline();
+}
+
+void w_as_c_string_in_data_section (char *string,int length)
+{
+ int n;
+
+ w_as_to_data_section();
+
+ n=w_as_data (0,string,length);
+ if (length & 3)
+ n=w_as_zeros (n,4-(length & 3));
+ /* CHANGED 30-7-92 */
+ else
+ n=w_as_zeros (n,4);
+ /* */
+ if (n>0)
+ w_as_newline();
+}
+
+void w_as_abc_string_in_data_section (char *string,int length)
+{
+ int n;
+
+ w_as_to_data_section();
+
+ w_as_opcode (".long");
+ fprintf (assembly_file,"%d\n",length);
+ n=w_as_data (0,string,length);
+ if (length & 3)
+ n=w_as_zeros (n,4-(length & 3));
+ if (n>0)
+ w_as_newline();
+}
+
+void w_as_descriptor_string_in_data_section (char *string,int length,int string_label_id,LABEL *string_label)
+{
+ int n;
+
+ w_as_to_data_section();
+
+ w_as_define_internal_data_label (string_label_id);
+ w_as_define_local_data_label (string_label->label_number);
+
+ w_as_opcode (".long");
+ fprintf (assembly_file,"%d\n",length);
+ n=w_as_data (0,string,length);
+ if (length & 3)
+ n=w_as_zeros (n,4-(length & 3));
+ if (n>0)
+ w_as_newline();
+}
+
+enum { SIZE_LONG, SIZE_WORD, SIZE_BYTE };
+
+static void w_as_label (char *label)
+{
+ int c;
+
+ while ((c=*label++)!=0)
+ putc (c,assembly_file);
+}
+
+#define MAX_LITERAL_INSTRUCTION_OFFSET 1023
+
+static unsigned int instruction_n_after_ltorg,ltorg_at_instruction_n;
+
+static void w_as_local_label (int label_number)
+{
+ fprintf (assembly_file,"l_%d",label_number);
+}
+
+static void w_as_label_parameter (struct parameter *parameter_p)
+{
+ if (parameter_p->parameter_data.l->label_number!=0)
+ w_as_local_label (parameter_p->parameter_data.l->label_number);
+ else
+ w_as_label (parameter_p->parameter_data.l->label_name);
+}
+
+static void w_as_immediate_label (LABEL *label)
+{
+ if (instruction_n_after_ltorg+MAX_LITERAL_INSTRUCTION_OFFSET < ltorg_at_instruction_n)
+ ltorg_at_instruction_n = instruction_n_after_ltorg+MAX_LITERAL_INSTRUCTION_OFFSET;
+
+ putc ('=',assembly_file);
+ if (label->label_number!=0)
+ w_as_local_label (label->label_number);
+ else
+ w_as_label (label->label_name);
+}
+
+static void w_as_immediate_label_name (char *label_name)
+{
+ if (instruction_n_after_ltorg+MAX_LITERAL_INSTRUCTION_OFFSET < ltorg_at_instruction_n)
+ ltorg_at_instruction_n = instruction_n_after_ltorg+MAX_LITERAL_INSTRUCTION_OFFSET;
+
+ putc ('=',assembly_file);
+ w_as_label (label_name);
+}
+
+static void w_as_colon (VOID)
+{
+ putc (':',assembly_file);
+}
+
+static void w_as_define_label_name (char *label_name)
+{
+ w_as_label (label_name);
+ w_as_colon();
+ w_as_newline();
+}
+
+static void w_as_define_data_label_name (char *label_name)
+{
+ w_as_label (label_name);
+ w_as_colon();
+ w_as_newline();
+}
+
+void w_as_define_label (LABEL *label)
+{
+ if (label->label_flags & EXPORT_LABEL){
+ w_as_opcode (".globl");
+ w_as_label (label->label_name);
+ w_as_newline();
+ }
+
+ w_as_label (label->label_name);
+ w_as_colon();
+ w_as_newline();
+}
+
+static void w_as_define_code_label (LABEL *label)
+{
+ if (label->label_flags & EXPORT_LABEL){
+ w_as_opcode (".globl");
+ w_as_label (label->label_name);
+ w_as_newline();
+ }
+
+ w_as_label (label->label_name);
+ w_as_colon();
+ w_as_newline();
+}
+
+static void w_as_internal_label (int label_number)
+{
+ fprintf (assembly_file,"i_%d",label_number);
+}
+
+static void w_as_immediate (LONG i)
+{
+ fprintf (assembly_file,"#%ld",i);
+}
+
+void w_as_abc_string_and_label_in_data_section (char *string,int length,char *label_name)
+{
+ int n;
+
+ w_as_to_data_section();
+
+ w_as_define_data_label_name (label_name);
+
+ w_as_opcode (".long");
+ fprintf (assembly_file,"%d\n",length);
+ n=w_as_data (0,string,length);
+ if (length & 3)
+ n=w_as_zeros (n,4-(length & 3));
+ if (n>0)
+ w_as_newline();
+}
+
+static char *register_name[15]={"sp","r10","r9","r11","r8","r7","r6","r4","r3","r2","r1","r0","r5","r12","r14"};
+
+#define REGISTER_S0 6
+#define REGISTER_S1 7
+
+static void w_as_indirect (int i,int reg)
+{
+ if (i==0)
+ fprintf (assembly_file,"[%s]",register_name[reg+7]);
+ else
+ fprintf (assembly_file,"[%s,#%d]",register_name[reg+7],i);
+}
+
+static void w_as_indirect_with_update (int i,int reg)
+{
+ if (i==0)
+ fprintf (assembly_file,"[%s]",register_name[reg+7]);
+ else
+ fprintf (assembly_file,"[%s,#%d]!",register_name[reg+7],i);
+}
+
+static void w_as_indirect_post_add (int i,int reg)
+{
+ if (i==0)
+ fprintf (assembly_file,"[%s]",register_name[reg+7]);
+ else
+ fprintf (assembly_file,"[%s],#%d",register_name[reg+7],i);
+}
+
+static void w_as_register (int reg)
+{
+ fputs (register_name[reg+7],assembly_file);
+}
+
+static void w_as_comma (VOID)
+{
+ putc (',',assembly_file);
+}
+
+static void w_as_register_comma (int reg)
+{
+ w_as_register (reg);
+ w_as_comma();
+}
+
+static void w_as_comma_register (int reg)
+{
+ w_as_comma();
+ w_as_register (reg);
+}
+
+static void w_as_indexed_no_offset (int offset,int reg1,int reg2)
+{
+ int shift;
+
+ shift=offset & 3;
+ if (shift!=0)
+ fprintf (assembly_file,"[%s,%s,lsl #%d]",register_name[reg1+7],register_name[reg2+7],shift);
+ else
+ fprintf (assembly_file,"[%s,%s]",register_name[reg1+7],register_name[reg2+7]);
+}
+
+static void w_as_indexed_no_offset_ir (int offset,struct index_registers *index_registers)
+{
+ w_as_indexed_no_offset (offset,index_registers->a_reg.r,index_registers->d_reg.r);
+}
+
+struct float_constant {
+ DOUBLE * float_constant_r_p;
+ int float_constant_label_number;
+ struct float_constant * float_constant_next;
+};
+
+struct float_constant *first_float_constant,**float_constant_l;
+
+static void write_float_constants (void)
+{
+ struct float_constant *float_constant;
+
+ float_constant=first_float_constant;
+
+ if (float_constant!=NULL){
+ w_as_align (3);
+
+ for (; float_constant!=NULL; float_constant=float_constant->float_constant_next){
+ w_as_define_internal_data_label (float_constant->float_constant_label_number);
+
+ w_as_opcode (".double");
+ fprintf (assembly_file,"0r%.20e",*float_constant->float_constant_r_p);
+ w_as_newline();
+ }
+
+ float_constant_l=&first_float_constant;
+ first_float_constant=NULL;
+ }
+}
+
+static void w_as_newline_after_instruction (VOID)
+{
+ w_as_newline();
+ ++instruction_n_after_ltorg;
+ if (instruction_n_after_ltorg>=ltorg_at_instruction_n){
+ int label_id;
+
+ label_id=next_label_id++;
+
+ w_as_opcode ("b");
+ w_as_internal_label (label_id);
+ w_as_newline();
+
+ write_float_constants();
+ w_as_opcode (".ltorg");
+ w_as_newline();
+
+ w_as_define_internal_label (label_id);
+
+ instruction_n_after_ltorg = 0u;
+ ltorg_at_instruction_n = 0u-1u;
+ }
+}
+
+static void w_as_register_newline (int reg)
+{
+ w_as_register (reg);
+ w_as_newline_after_instruction();
+}
+
+static void w_as_indirect_newline (int i,int reg)
+{
+ w_as_indirect (i,reg);
+ w_as_newline_after_instruction();
+}
+
+static void w_as_indirect_with_update_newline (int i,int reg)
+{
+ w_as_indirect_with_update (i,reg);
+ w_as_newline_after_instruction();
+}
+
+static void w_as_indirect_post_add_newline (int i,int reg)
+{
+ w_as_indirect_post_add (i,reg);
+ w_as_newline_after_instruction();
+}
+
+static void w_as_immediate_newline (LONG i)
+{
+ fprintf (assembly_file,"#%ld",i);
+ w_as_newline_after_instruction();
+}
+
+void w_as_c_string_and_label_in_code_section (char *string,int length,char *label_name)
+{
+ int n;
+
+/* w_as_to_code_section(); */
+ w_as_to_data_section();
+
+ w_as_define_data_label_name (label_name);
+
+ n=w_as_data (0,string,length);
+ n=w_as_zeros (n,4-(length & 3));
+ if (n>0)
+ w_as_newline();
+}
+
+static void w_as_scratch_register (void)
+{
+ fprintf (assembly_file,"r12");
+}
+
+static void w_as_scratch_register_comma (void)
+{
+ fprintf (assembly_file,"r12");
+ w_as_comma();
+}
+
+static void w_as_comma_scratch_register (void)
+{
+ w_as_comma();
+ fprintf (assembly_file,"r12");
+}
+
+static void w_as_comma_scratch_register_newline (void)
+{
+ w_as_comma();
+ fprintf (assembly_file,"r12");
+ w_as_newline_after_instruction();
+}
+
+static void w_as_fp_register (int fp_reg)
+{
+ fprintf (assembly_file,"d%d",fp_reg);
+}
+
+static void w_as_fp_register_comma (int fp_reg)
+{
+ fprintf (assembly_file,"d%d,",fp_reg);
+}
+
+static void w_as_fp_register_newline (int fp_reg)
+{
+ fprintf (assembly_file,"d%d",fp_reg);
+ w_as_newline_after_instruction();
+}
+
+static void w_as_descriptor (LABEL *label,int arity)
+{
+ if (instruction_n_after_ltorg+MAX_LITERAL_INSTRUCTION_OFFSET < ltorg_at_instruction_n)
+ ltorg_at_instruction_n = instruction_n_after_ltorg+MAX_LITERAL_INSTRUCTION_OFFSET;
+
+ putc ('=',assembly_file);
+ if (label->label_number!=0)
+ w_as_local_label (label->label_number);
+ else
+ w_as_label (label->label_name);
+
+ if (arity!=0)
+ if (arity>0)
+ fprintf (assembly_file,"+%d",arity);
+ else
+ fprintf (assembly_file,"-%d",-arity);
+}
+
+static int mov_or_mvn_immediate (unsigned int i)
+{
+ if ((i & ~0xff)==0) return 1;
+ if ((i & ~0x3fc)==0) return 1;
+ if ((i & ~0xff0)==0) return 1;
+ if ((i & ~0x3fc0)==0) return 1;
+ if ((i & ~0xff00)==0) return 1;
+ if ((i & ~0x3fc00)==0) return 1;
+ if ((i & ~0xff000)==0) return 1;
+ if ((i & ~0x3fc000)==0) return 1;
+ if ((i & ~0xff0000)==0) return 1;
+ if ((i & ~0x3fc0000)==0) return 1;
+ if ((i & ~0xff00000)==0) return 1;
+ if ((i & ~0x3fc00000)==0) return 1;
+ if ((i & ~0xff000000)==0) return 1;
+ if ((i & ~0xfc000003)==0) return 1;
+ if ((i & ~0xf000000f)==0) return 1;
+ if ((i & ~0xc000003f)==0) return 1;
+
+ i = ~i;
+
+ if ((i & ~0xff)==0) return 1;
+ if ((i & ~0x3fc)==0) return 1;
+ if ((i & ~0xff0)==0) return 1;
+ if ((i & ~0x3fc0)==0) return 1;
+ if ((i & ~0xff00)==0) return 1;
+ if ((i & ~0x3fc00)==0) return 1;
+ if ((i & ~0xff000)==0) return 1;
+ if ((i & ~0x3fc000)==0) return 1;
+ if ((i & ~0xff0000)==0) return 1;
+ if ((i & ~0x3fc0000)==0) return 1;
+ if ((i & ~0xff00000)==0) return 1;
+ if ((i & ~0x3fc00000)==0) return 1;
+ if ((i & ~0xff000000)==0) return 1;
+ if ((i & ~0xfc000003)==0) return 1;
+ if ((i & ~0xf000000f)==0) return 1;
+ if ((i & ~0xc000003f)==0) return 1;
+
+ return 0;
+}
+
+static void w_as_opcode_mov (void)
+{
+ w_as_opcode ("mov");
+}
+
+static void w_as_opcode_load (int size_flag)
+{
+ w_as_opcode (size_flag==SIZE_LONG ? "ldr" : size_flag==SIZE_WORD ? "ldrsh" : "ldrb");
+}
+
+static void w_as_ld_indexed (struct parameter *parameter_p,int dreg,int size_flag)
+{
+ int offset;
+
+ offset=parameter_p->parameter_offset;
+ if ((offset & -4)!=0){
+ int reg1,reg2;
+
+ reg1=parameter_p->parameter_data.ir->a_reg.r;
+ reg2=parameter_p->parameter_data.ir->d_reg.r;
+
+ w_as_opcode ("add");
+ w_as_scratch_register_comma();
+ w_as_register_comma (reg1);
+ w_as_immediate_newline (offset>>2);
+
+ w_as_opcode_load (size_flag);
+ w_as_register_comma (dreg);
+ w_as_indexed_no_offset (offset,REGISTER_S0,reg2);
+ w_as_newline_after_instruction();
+ } else {
+ w_as_opcode_load (size_flag);
+ w_as_register_comma (dreg);
+ w_as_indexed_no_offset_ir (offset,parameter_p->parameter_data.ir);
+ w_as_newline_after_instruction();
+ }
+}
+
+static int w_as_register_parameter (struct parameter *parameter_p)
+{
+ switch (parameter_p->parameter_type){
+ case P_REGISTER:
+ return parameter_p->parameter_data.reg.r;
+ case P_LABEL:
+ w_as_opcode ("ldr");
+ w_as_scratch_register_comma();
+ w_as_immediate_label (parameter_p->parameter_data.l);
+ w_as_newline_after_instruction();
+ return REGISTER_S0;
+ case P_IMMEDIATE:
+ {
+ int i;
+
+ i=parameter_p->parameter_data.i;
+ if (mov_or_mvn_immediate (i)){
+ w_as_opcode_mov();
+ w_as_scratch_register_comma();
+ w_as_immediate_newline (i);
+ } else {
+ if (instruction_n_after_ltorg+MAX_LITERAL_INSTRUCTION_OFFSET < ltorg_at_instruction_n)
+ ltorg_at_instruction_n = instruction_n_after_ltorg+MAX_LITERAL_INSTRUCTION_OFFSET;
+
+ w_as_opcode ("ldr");
+ w_as_scratch_register_comma();
+ fprintf (assembly_file,"=%d",i);
+ w_as_newline_after_instruction();
+ }
+ return REGISTER_S0;
+ }
+ case P_INDIRECT:
+ w_as_opcode ("ldr");
+ w_as_scratch_register_comma();
+ w_as_indirect_newline (parameter_p->parameter_offset,parameter_p->parameter_data.reg.r);
+ return REGISTER_S0;
+ case P_INDEXED:
+ w_as_ld_indexed (parameter_p,REGISTER_S0,SIZE_LONG);
+ return REGISTER_S0;
+ case P_INDIRECT_WITH_UPDATE:
+ w_as_opcode ("ldr");
+ w_as_scratch_register_comma;
+ w_as_indirect_with_update_newline (parameter_p->parameter_offset,parameter_p->parameter_data.reg.r);
+ return REGISTER_S0;
+ case P_PRE_DECREMENT:
+ w_as_opcode ("ldr");
+ w_as_scratch_register_comma();
+ fprintf (assembly_file,"[sp,#-4]");
+ w_as_newline_after_instruction();
+ return REGISTER_S0;
+ case P_POST_INCREMENT:
+ w_as_opcode ("ldr");
+ w_as_scratch_register_comma();
+ fprintf (assembly_file,"[sp],#4");
+ w_as_newline_after_instruction();
+ return REGISTER_S0;
+ case P_INDIRECT_POST_ADD:
+ w_as_opcode ("ldr");
+ w_as_scratch_register_comma();
+ w_as_indirect_post_add_newline (parameter_p->parameter_offset,parameter_p->parameter_data.reg.r);
+ return REGISTER_S0;
+ case P_F_REGISTER:
+ w_as_opcode ("ldr");
+ w_as_scratch_register_comma();
+ fprintf (assembly_file,"%%st(%d)",parameter_p->parameter_data.reg.r<<1);
+ w_as_newline_after_instruction();
+ return REGISTER_S0;
+ default:
+ internal_error_in_function ("w_as_register_parameter");
+ }
+}
+
+static void w_as_jump_parameter (register struct parameter *parameter)
+{
+ switch (parameter->parameter_type){
+ case P_LABEL:
+ if (parameter->parameter_data.l->label_number!=0)
+ w_as_local_label (parameter->parameter_data.l->label_number);
+ else
+ w_as_label (parameter->parameter_data.l->label_name);
+ break;
+ case P_INDIRECT:
+ {
+ int offset,reg;
+
+ offset=parameter->parameter_offset;
+ reg=parameter->parameter_data.reg.r;
+
+ if (offset!=0)
+ fprintf (assembly_file,"%d(%%%s)",offset,register_name[reg+7]);
+ else
+ fprintf (assembly_file,"(%%%s)",register_name[reg+7]);
+ break;
+ }
+ case P_REGISTER:
+ {
+ int reg;
+
+ reg=parameter->parameter_data.reg.r;
+
+ fprintf (assembly_file,"%s",register_name[reg+7]);
+ break;
+ }
+ default:
+ internal_error_in_function ("w_as_jump_parameter");
+ }
+}
+
+static void w_as_opcode_store (int size_flag)
+{
+ w_as_opcode (size_flag==SIZE_LONG ? "str" : size_flag==SIZE_WORD ? "strh" : "strb");
+}
+
+static void w_as_register_register_newline (int reg1,int reg2)
+{
+ w_as_register_comma (reg1);
+ w_as_register (reg2);
+ w_as_newline_after_instruction();
+}
+
+static void w_as_opcode_register_newline (char *opcode,int reg1)
+{
+ w_as_opcode (opcode);
+ w_as_register (reg1);
+ w_as_newline_after_instruction();
+}
+
+static void w_as_opcode_register_register_newline (char *opcode,int reg1,int reg2)
+{
+ w_as_opcode (opcode);
+ w_as_register_register_newline (reg1,reg2);
+}
+
+static void w_as_movl_register_register_newline (int reg1,int reg2)
+{
+ w_as_opcode_mov();
+ w_as_register_register_newline (reg1,reg2);
+}
+
+static void w_as_immediate_register_newline (int i,int reg)
+{
+ w_as_immediate (i);
+ w_as_comma_register (reg);
+ w_as_newline_after_instruction();
+}
+
+static void w_as_ld_large_immediate (int i,int reg)
+{
+ if (instruction_n_after_ltorg+MAX_LITERAL_INSTRUCTION_OFFSET < ltorg_at_instruction_n)
+ ltorg_at_instruction_n = instruction_n_after_ltorg+MAX_LITERAL_INSTRUCTION_OFFSET;
+
+ w_as_opcode ("ldr");
+ w_as_register_comma (reg);
+ fprintf (assembly_file,"=%d",i);
+ w_as_newline_after_instruction();
+}
+
+static void w_as_ld_immediate (int i,int reg)
+{
+ if (mov_or_mvn_immediate (i)){
+ w_as_opcode_mov();
+ w_as_register_comma (reg);
+ w_as_immediate_newline (i);
+ } else
+ w_as_ld_large_immediate (i,reg);
+}
+
+static void w_as_move_instruction (struct instruction *instruction,int size_flag)
+{
+ if (instruction->instruction_parameters[1].parameter_type==P_REGISTER){
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_DESCRIPTOR_NUMBER:
+ w_as_opcode ("ldr");
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_descriptor (instruction->instruction_parameters[0].parameter_data.l,
+ instruction->instruction_parameters[0].parameter_offset);
+ w_as_newline_after_instruction();
+ return;
+ case P_IMMEDIATE:
+ w_as_ld_immediate (instruction->instruction_parameters[0].parameter_data.i,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_REGISTER:
+ w_as_opcode_mov();
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r);
+ w_as_newline_after_instruction();
+ return;
+ case P_INDIRECT:
+ w_as_opcode_load (size_flag);
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_indirect_newline (instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ return;
+ case P_INDEXED:
+ w_as_ld_indexed (&instruction->instruction_parameters[0],
+ instruction->instruction_parameters[1].parameter_data.reg.r,size_flag);
+ return;
+ case P_INDIRECT_WITH_UPDATE:
+ w_as_opcode_load (size_flag);
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_indirect_with_update_newline (instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ return;
+ case P_POST_INCREMENT:
+ w_as_opcode ("ldr");
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ fprintf (assembly_file,"[sp],#4");
+ w_as_newline_after_instruction();
+ return;
+ case P_INDIRECT_POST_ADD:
+ w_as_opcode ("ldr");
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_indirect_post_add_newline (instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ return;
+ case P_LABEL:
+ w_as_opcode_mov();
+ w_as_label_parameter (&instruction->instruction_parameters[0]);
+ w_as_comma_register (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_newline_after_instruction();
+ return;
+ }
+ internal_error_in_function ("w_as_move_instruction");
+ return;
+ } else {
+ struct parameter parameter;
+ int s_reg;
+
+ parameter=instruction->instruction_parameters[0];
+
+ switch (parameter.parameter_type){
+ case P_REGISTER:
+ s_reg=parameter.parameter_data.reg.r;
+ break;
+ case P_INDIRECT:
+ w_as_opcode_load (size_flag);
+ w_as_scratch_register_comma();
+ w_as_indirect_newline (parameter.parameter_offset,parameter.parameter_data.reg.r);
+ s_reg = REGISTER_S0;
+ break;
+ case P_INDEXED:
+ w_as_ld_indexed (&parameter,REGISTER_S0,size_flag);
+ s_reg = REGISTER_S0;
+ break;
+ case P_DESCRIPTOR_NUMBER:
+ w_as_opcode ("ldr");
+ w_as_scratch_register();
+ w_as_comma();
+ w_as_descriptor (parameter.parameter_data.l,parameter.parameter_offset);
+ w_as_newline_after_instruction();
+ s_reg = REGISTER_S0;
+ break;
+ case P_IMMEDIATE:
+ w_as_ld_immediate (instruction->instruction_parameters[0].parameter_data.i,REGISTER_S0);
+ s_reg = REGISTER_S0;
+ break;
+ case P_POST_INCREMENT:
+ w_as_opcode ("ldr");
+ w_as_scratch_register();
+ fprintf (assembly_file,",[sp],#4");
+ w_as_newline_after_instruction();
+ s_reg = REGISTER_S0;
+ break;
+ case P_INDIRECT_WITH_UPDATE:
+ w_as_opcode ("ldr");
+ w_as_scratch_register_comma();
+ w_as_indirect_with_update (parameter.parameter_offset,parameter.parameter_data.reg.r);
+ w_as_newline_after_instruction();
+ s_reg = REGISTER_S0;
+ break;
+ case P_INDIRECT_POST_ADD:
+ w_as_opcode ("ldr");
+ w_as_scratch_register_comma();
+ w_as_indirect_post_add (parameter.parameter_offset,parameter.parameter_data.reg.r);
+ w_as_newline_after_instruction();
+ s_reg = REGISTER_S0;
+ break;
+ default:
+ internal_error_in_function ("w_as_move_instruction");
+ return;
+ }
+
+ switch (instruction->instruction_parameters[1].parameter_type){
+ case P_INDIRECT:
+ w_as_opcode (size_flag==SIZE_LONG ? "str" : size_flag==SIZE_WORD ? "strh" : "strb");
+ w_as_register_comma (s_reg);
+ w_as_indirect_newline (instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_PRE_DECREMENT:
+ w_as_opcode ("str");
+ w_as_register (s_reg);
+ fprintf (assembly_file,",[sp,#-4]!");
+ w_as_newline_after_instruction();
+ return;
+ case P_INDEXED:
+ {
+ int offset;
+
+ offset=instruction->instruction_parameters[1].parameter_offset;
+ if ((offset & -4)!=0){
+ int reg1,reg2,reg3;
+
+ reg1=instruction->instruction_parameters[1].parameter_data.ir->a_reg.r;
+ reg2=instruction->instruction_parameters[1].parameter_data.ir->d_reg.r;
+
+ if (s_reg==REGISTER_S0)
+ reg3=REGISTER_S1;
+ else
+ reg3=REGISTER_S0;
+
+ w_as_opcode ("add");
+ w_as_register_comma (reg3);
+ w_as_register_comma (reg1);
+ w_as_immediate_newline (offset>>2);
+
+ w_as_opcode_store (size_flag);
+ w_as_register_comma (s_reg);
+ w_as_indexed_no_offset (offset,reg3,reg2);
+ w_as_newline_after_instruction();
+ } else {
+ w_as_opcode_store (size_flag);
+ w_as_register_comma (s_reg);
+ w_as_indexed_no_offset_ir (instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.ir);
+ w_as_newline_after_instruction();
+ }
+ return;
+ }
+ case P_INDIRECT_WITH_UPDATE:
+ w_as_opcode (size_flag==SIZE_LONG ? "str" : size_flag==SIZE_WORD ? "strh" : "strb");
+ w_as_register_comma (s_reg);
+ w_as_indirect_with_update_newline (instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_INDIRECT_POST_ADD:
+ w_as_opcode (size_flag==SIZE_LONG ? "str" : size_flag==SIZE_WORD ? "strh" : "strb");
+ w_as_register_comma (s_reg);
+ w_as_indirect_post_add_newline (instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_LABEL:
+ w_as_opcode_mov();
+ w_as_register_comma (s_reg);
+ w_as_label_parameter (&instruction->instruction_parameters[1]);
+ w_as_newline_after_instruction();
+ return;
+ default:
+ internal_error_in_function ("w_as_move_instruction");
+ }
+ }
+}
+
+static void w_as_movem_instruction (struct instruction *instruction)
+{
+ int n_regs;
+
+ n_regs = instruction->instruction_arity-1;
+
+ if (instruction->instruction_parameters[0].parameter_type!=P_REGISTER){
+ int s_reg,reg_n;
+
+ if (instruction->instruction_parameters[0].parameter_type==P_PRE_DECREMENT)
+ w_as_opcode ("ldmdb");
+ else if (instruction->instruction_parameters[0].parameter_type==P_POST_INCREMENT)
+ w_as_opcode ("ldmia");
+ else {
+ internal_error_in_function ("w_as_movem_instruction");
+ return;
+ }
+
+ w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r);
+ fprintf (assembly_file,"!,{");
+ w_as_register (instruction->instruction_parameters[1].parameter_data.reg.r);
+ for (reg_n=1; reg_n<n_regs; ++reg_n)
+ w_as_comma_register (instruction->instruction_parameters[1+reg_n].parameter_data.reg.r);
+ fprintf (assembly_file,"}");
+ w_as_newline_after_instruction();
+
+ return;
+ } else {
+ int d_reg,reg_n;
+
+ if (instruction->instruction_parameters[n_regs].parameter_type==P_PRE_DECREMENT)
+ w_as_opcode ("stmdb");
+ else if (instruction->instruction_parameters[n_regs].parameter_type==P_POST_INCREMENT)
+ w_as_opcode ("stmia");
+ else {
+ internal_error_in_function ("w_as_movem_instruction");
+ return;
+ }
+
+ w_as_register (instruction->instruction_parameters[n_regs].parameter_data.reg.r);
+ fprintf (assembly_file,"!,{");
+ w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r);
+ for (reg_n=1; reg_n<n_regs; ++reg_n)
+ w_as_comma_register (instruction->instruction_parameters[reg_n].parameter_data.reg.r);
+ fprintf (assembly_file,"}");
+ w_as_newline_after_instruction();
+
+ return;
+ }
+
+ internal_error_in_function ("w_as_movem_instruction");
+}
+
+static void w_as_lea_instruction (struct instruction *instruction)
+{
+ if (instruction->instruction_parameters[1].parameter_type==P_REGISTER){
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_INDIRECT:
+ w_as_opcode ("add");
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_register_comma (instruction->instruction_parameters[0].parameter_data.reg.r);
+ fprintf (assembly_file,"#%d",instruction->instruction_parameters[0].parameter_offset);
+ w_as_newline_after_instruction();
+ return;
+ case P_INDEXED:
+ if (instruction->instruction_parameters[0].parameter_offset==0){
+ w_as_opcode ("add");
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_register_comma (instruction->instruction_parameters[0].parameter_data.ir->a_reg.r);
+ w_as_register_newline (instruction->instruction_parameters[0].parameter_data.ir->d_reg.r);
+ return;
+ }
+ break;
+ case P_LABEL:
+ if (instruction_n_after_ltorg+MAX_LITERAL_INSTRUCTION_OFFSET < ltorg_at_instruction_n)
+ ltorg_at_instruction_n = instruction_n_after_ltorg+MAX_LITERAL_INSTRUCTION_OFFSET;
+
+ w_as_opcode ("ldr");
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ putc ('=',assembly_file);
+ w_as_label_parameter (&instruction->instruction_parameters[0]);
+ if (instruction->instruction_parameters[0].parameter_offset!=0){
+ int offset;
+
+ offset=instruction->instruction_parameters[0].parameter_offset;
+ fprintf (assembly_file,offset>=0 ? "+%d" : "%d",offset);
+ }
+ w_as_newline_after_instruction();
+ return;
+ }
+ }
+ internal_error_in_function ("w_as_lea_instruction");
+}
+
+static void w_as_dyadic_instruction (struct instruction *instruction,char *opcode)
+{
+ if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE &&
+ mov_or_mvn_immediate (instruction->instruction_parameters[0].parameter_data.i))
+ {
+ w_as_opcode (opcode);
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_immediate_newline (instruction->instruction_parameters[0].parameter_data.i);
+ } else {
+ int reg0;
+
+ reg0 = w_as_register_parameter (&instruction->instruction_parameters[0]);
+
+ w_as_opcode (opcode);
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_register_newline (reg0);
+ }
+}
+
+static void w_as_reg_reg_imm_instruction (struct instruction *instruction,char *opcode)
+{
+ if (mov_or_mvn_immediate (instruction->instruction_parameters[2].parameter_data.i)){
+ w_as_opcode (opcode);
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_register_comma (instruction->instruction_parameters[0].parameter_data.reg.r);
+ w_as_immediate_newline (instruction->instruction_parameters[2].parameter_data.i);
+ } else {
+ int reg0;
+
+ reg0 = w_as_register_parameter (&instruction->instruction_parameters[2]);
+
+ w_as_opcode (opcode);
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_register_comma (instruction->instruction_parameters[0].parameter_data.reg.r);
+ w_as_register_newline (reg0);
+ }
+}
+
+static void w_as_mul_instruction (struct instruction *instruction)
+{
+ if (instruction->instruction_parameters[0].parameter_type==P_REGISTER){
+ int reg0,reg1;
+
+ reg0 = instruction->instruction_parameters[0].parameter_data.reg.r;
+ reg1 = instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ if (reg0==reg1){
+ w_as_opcode_mov();
+ w_as_scratch_register_comma();
+ w_as_register (reg0);
+ w_as_newline_after_instruction();
+ reg0 = REGISTER_S0;
+ }
+
+ w_as_opcode ("mul");
+ w_as_register_comma (reg1);
+ w_as_register_comma (reg0);
+ w_as_register_newline (reg1);
+ } else if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT){
+ int reg0;
+
+ reg0 = w_as_register_parameter (&instruction->instruction_parameters[0]);
+
+ w_as_opcode ("mul");
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_register_comma (reg0);
+ w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r);
+ } else {
+ int reg0;
+
+ reg0 = w_as_register_parameter (&instruction->instruction_parameters[0]);
+
+ w_as_opcode ("mul");
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_register_comma (reg0);
+ w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r);
+ }
+}
+
+static void w_as_shift_instruction (struct instruction *instruction,char *opcode)
+{
+ if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){
+ w_as_opcode (opcode);
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_immediate_newline (instruction->instruction_parameters[0].parameter_data.i & 31);
+ } else {
+ w_as_opcode (opcode);
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_register_newline (instruction->instruction_parameters[0].parameter_data.reg.r);
+ }
+}
+
+static void w_as_cmp_instruction (struct instruction *instruction)
+{
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_DESCRIPTOR_NUMBER:
+ {
+ int reg1,reg2;
+
+ reg1 = w_as_register_parameter (&instruction->instruction_parameters[1]);
+ reg2 = reg1!=REGISTER_S0 ? REGISTER_S0 : REGISTER_S1;
+
+ w_as_opcode ("ldr");
+ w_as_register_comma (reg2);
+ w_as_descriptor (instruction->instruction_parameters[0].parameter_data.l,
+ instruction->instruction_parameters[0].parameter_offset);
+ w_as_newline_after_instruction();
+
+ w_as_opcode ("cmp");
+ w_as_register_comma (reg1);
+ w_as_register_newline (reg2);
+ return;
+ }
+ case P_IMMEDIATE:
+ {
+ int reg1;
+
+ reg1 = w_as_register_parameter (&instruction->instruction_parameters[1]);
+
+ if (mov_or_mvn_immediate (instruction->instruction_parameters[0].parameter_data.i)){
+ w_as_opcode ("cmp");
+ w_as_register_comma (reg1);
+ w_as_immediate_newline (instruction->instruction_parameters[0].parameter_data.i);
+ return;
+ } else {
+ int reg2;
+
+ reg2 = reg1!=REGISTER_S0 ? REGISTER_S0 : REGISTER_S1;
+
+ w_as_ld_large_immediate (instruction->instruction_parameters[0].parameter_data.i,reg2);
+
+ w_as_opcode ("cmp");
+ w_as_register_comma (reg1);
+ w_as_register_newline (reg2);
+ return;
+ }
+ }
+ }
+
+ if (instruction->instruction_parameters[1].parameter_type==P_REGISTER){
+ int reg0;
+
+ reg0=w_as_register_parameter (&instruction->instruction_parameters[0]);
+
+ w_as_opcode ("cmp");
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_register_newline (reg0);
+ return;
+ }
+
+ internal_error_in_function ("w_as_cmp_instruction");
+}
+
+static void w_as_tst_instruction (struct instruction *instruction)
+{
+ int reg0;
+
+ reg0=w_as_register_parameter (&instruction->instruction_parameters[0]);
+
+ w_as_opcode ("cmp");
+ w_as_register_comma (reg0);
+ w_as_immediate_newline (0);
+}
+
+static void w_as_monadic_instruction (struct instruction *instruction,char *opcode)
+{
+ w_as_opcode (opcode);
+ w_as_register_comma (instruction->instruction_parameters[0].parameter_data.reg.r);
+ w_as_register_newline (instruction->instruction_parameters[0].parameter_data.reg.r);
+}
+
+static void w_as_btst_instruction (struct instruction *instruction)
+{
+ if (instruction->instruction_parameters[1].parameter_type==P_REGISTER){
+ w_as_opcode ("tst");
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_immediate_newline (instruction->instruction_parameters[0].parameter_data.i);
+ } else {
+ w_as_opcode ("ldr");
+ w_as_scratch_register_comma();
+ w_as_indirect_newline (instruction->instruction_parameters[1].parameter_offset,instruction->instruction_parameters[1].parameter_data.reg.r);
+
+ w_as_opcode ("tst");
+ w_as_scratch_register_comma();
+ w_as_immediate_newline (instruction->instruction_parameters[0].parameter_data.i);
+ }
+}
+
+void w_as_jmp_instruction (struct instruction *instruction)
+{
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_INDIRECT:
+ w_as_opcode ("ldr");
+ fputs ("pc,",assembly_file);
+ w_as_indirect_newline (instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ break;
+ case P_REGISTER:
+ w_as_opcode_mov();
+ fputs ("pc",assembly_file);
+ w_as_comma();
+ w_as_register_newline (instruction->instruction_parameters[0].parameter_data.reg.r);
+ break;
+ default:
+ w_as_opcode ("b");
+ w_as_jump_parameter (&instruction->instruction_parameters[0]);
+ w_as_newline_after_instruction();
+ }
+ write_float_constants();
+ w_as_opcode (".ltorg");
+ w_as_newline();
+ instruction_n_after_ltorg = 0u;
+ ltorg_at_instruction_n = 0u-1u;
+}
+
+void w_as_jmpp_instruction (struct instruction *instruction)
+{
+#if 0
+ struct parameter *parameter_p;
+
+ parameter_p=&instruction->instruction_parameters[0];
+
+ switch (parameter_p->parameter_type){
+ case P_LABEL:
+ {
+ int offset;
+
+ offset=parameter_p->parameter_offset;
+
+ if (offset==0){
+ w_as_opcode ("call");
+ w_as_label ("profile_t");
+ w_as_newline_after_instruction();
+ }
+
+ w_as_opcode ("jmp");
+ if (parameter_p->parameter_data.l->label_number!=0)
+ w_as_local_label (parameter_p->parameter_data.l->label_number);
+ else
+ w_as_label (parameter_p->parameter_data.l->label_name);
+
+ if (offset!=0)
+ fprintf (assembly_file,"+%d",offset);
+
+ break;
+ }
+ case P_INDIRECT:
+ case P_REGISTER:
+ w_as_opcode ("call");
+ w_as_label ("profile_t");
+ w_as_newline_after_instruction();
+
+ w_as_opcode ("jmp");
+ w_as_jump_parameter (&instruction->instruction_parameters[0]);
+ break;
+ default:
+ internal_error_in_function ("w_as_jmpp_instruction");
+ }
+
+ w_as_newline_after_instruction();
+#else
+ internal_error_in_function ("w_as_jmpp_instruction");
+#endif
+}
+
+static void w_as_branch_instruction (struct instruction *instruction,char *opcode)
+{
+ w_as_opcode (opcode);
+ w_as_label_parameter (&instruction->instruction_parameters[0]);
+ w_as_newline_after_instruction();
+}
+
+static void as_test_floating_point_condition_code (void)
+{
+ w_as_opcode ("fmstat");
+ w_as_newline_after_instruction();
+}
+
+static void w_as_float_branch_instruction (struct instruction *instruction,char *opcode)
+{
+ as_test_floating_point_condition_code();
+
+ /* Z N C V
+ equal 1 0 1 0
+ less than 0 1 0 0
+ greater than 0 0 1 0
+ unordered 0 0 1 1
+
+ bgt Z==0 && N==V
+ ble Z==1 || N!=V
+ */
+ w_as_opcode (opcode);
+ w_as_label_parameter (&instruction->instruction_parameters[0]);
+ w_as_newline_after_instruction();
+}
+
+static void w_as_jsr_instruction (struct instruction *instruction)
+{
+ if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT){
+ w_as_opcode ("ldr");
+ w_as_scratch_register_comma();
+ w_as_indirect_newline (instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+
+ if (instruction->instruction_arity>1)
+ switch (instruction->instruction_parameters[1].parameter_type){
+ case P_INDIRECT_WITH_UPDATE:
+ w_as_opcode ("str");
+ fprintf (assembly_file,"pc,[sp,#%d]!",instruction->instruction_parameters[1].parameter_offset);
+ w_as_newline_after_instruction();
+ }
+
+ w_as_opcode ("blx");
+ w_as_scratch_register();
+ w_as_newline_after_instruction();
+ } else {
+ if (instruction->instruction_arity>1)
+ switch (instruction->instruction_parameters[1].parameter_type){
+ case P_INDIRECT_WITH_UPDATE:
+ w_as_opcode ("str");
+ fprintf (assembly_file,"pc,[sp,#%d]!",instruction->instruction_parameters[1].parameter_offset);
+ w_as_newline_after_instruction();
+ break;
+ case P_INDIRECT:
+ w_as_opcode ("str");
+ fprintf (assembly_file,"pc,[sp,#%d]",instruction->instruction_parameters[1].parameter_offset);
+ w_as_newline_after_instruction();
+ break;
+ }
+
+ if (instruction->instruction_parameters[0].parameter_type==P_REGISTER)
+ w_as_opcode ("blx");
+ else
+ w_as_opcode ("bl");
+ w_as_jump_parameter (&instruction->instruction_parameters[0]);
+ w_as_newline_after_instruction();
+ }
+}
+
+static void w_as_set_condition_instruction (struct instruction *instruction,char *opcode1,char *opcode2)
+{
+ int r;
+ char *reg_s;
+
+ r=instruction->instruction_parameters[0].parameter_data.reg.r;
+
+ w_as_opcode (opcode1);
+ w_as_register (r);
+ fprintf (assembly_file,",#1");
+ w_as_newline_after_instruction();
+
+ w_as_opcode (opcode2);
+ w_as_register (r);
+ fprintf (assembly_file,",#0");
+ w_as_newline_after_instruction();
+}
+
+static void w_as_set_float_condition_instruction (struct instruction *instruction,char *opcode1,char *opcode2)
+{
+ as_test_floating_point_condition_code();
+ w_as_set_condition_instruction (instruction,opcode1,opcode2);
+}
+
+static void w_as_lsl_register_newline (int reg,int shift)
+{
+ w_as_register (reg);
+ if (shift!=0)
+ fprintf (assembly_file,",lsl #%d",shift);
+ w_as_newline_after_instruction();
+}
+
+static void w_as_lsr_register_newline (int reg,int shift)
+{
+ w_as_register (reg);
+ fprintf (assembly_file,",lsr #%d",shift);
+ w_as_newline_after_instruction();
+}
+
+static void w_as_lea_indexed_no_offset_ir (int s_reg,int offset,struct index_registers *index_registers)
+{
+ w_as_opcode ("add");
+ w_as_register_comma (s_reg);
+ w_as_register_comma (index_registers->a_reg.r);
+ w_as_lsl_register_newline (index_registers->d_reg.r,offset & 3);
+ w_as_newline_after_instruction();
+}
+
+static void w_as_div_instruction (struct instruction *instruction)
+{
+ int i,abs_i,d_reg;
+ struct ms ms;
+
+ d_reg=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ if (instruction->instruction_parameters[0].parameter_type!=P_IMMEDIATE){
+ internal_error_in_function ("w_as_div_instruction");
+ return;
+ }
+ i=instruction->instruction_parameters[0].parameter_data.i;
+
+ if (i==0){
+ internal_error_in_function ("w_as_div_instruction");
+ return;
+ }
+
+ abs_i=abs (i);
+
+ if ((abs_i & (abs_i-1))==0){
+ int log2i;
+ unsigned int i2;
+
+ if (abs_i==1){
+ if (i<0){
+ w_as_opcode ("neg");
+ w_as_register_comma (d_reg);
+ w_as_register_newline (d_reg);
+ }
+ return;
+ }
+
+ log2i=0;
+ i2=abs_i;
+ while (i2>1){
+ i2>>=1;
+ ++log2i;
+ }
+
+ if (log2i==1){
+ w_as_opcode ("add");
+ w_as_register_comma (d_reg);
+ w_as_register_comma (d_reg);
+ w_as_lsr_register_newline (d_reg,31);
+ } else {
+ w_as_opcode ("cmp");
+ w_as_register_comma (d_reg);
+ w_as_immediate_newline (0);
+
+ if (log2i<=8){
+ w_as_opcode ("addlt");
+ w_as_register_comma (d_reg);
+ w_as_register_comma (d_reg);
+ w_as_immediate_newline (abs_i-1);
+ } else {
+ w_as_opcode ("add");
+ w_as_scratch_register_comma();
+ w_as_register_comma (d_reg);
+ w_as_immediate_newline (abs_i);
+
+ w_as_opcode ("sublt");
+ w_as_register_comma (d_reg);
+ w_as_scratch_register_comma();
+ w_as_immediate_newline (1);
+ }
+ }
+
+ if (i>=0){
+ w_as_opcode ("asr");
+ w_as_register_comma (d_reg);
+ w_as_register_comma (d_reg);
+ w_as_immediate_newline (log2i);
+ } else {
+ w_as_opcode_mov();
+ w_as_scratch_register_comma();
+ w_as_immediate_newline (0);
+
+ w_as_opcode ("sub");
+ w_as_register_comma (d_reg);
+ w_as_scratch_register_comma();
+ w_as_register (d_reg);
+ fprintf (assembly_file,",asr #%d",log2i);
+ w_as_newline_after_instruction();
+ }
+ return;
+ }
+
+ ms=magic (abs_i);
+
+ w_as_ld_immediate (ms.m,REGISTER_S0);
+
+ if (ms.s==0){
+ if (ms.m>=0){
+ w_as_opcode ("lsr");
+ w_as_register_comma (REGISTER_S1);
+ w_as_register_comma (d_reg);
+ w_as_immediate_newline (31);
+
+ w_as_opcode ("smmla");
+ w_as_register_comma (d_reg);
+ w_as_register_comma (d_reg);
+ w_as_scratch_register_comma();
+ w_as_register_newline (REGISTER_S1);
+
+ if (i<0){
+ w_as_opcode ("neg");
+ w_as_register_comma (d_reg);
+ w_as_register_newline (d_reg);
+ }
+ } else {
+ if (ms.m>=0){
+ w_as_opcode ("smmul");
+ w_as_scratch_register_comma();
+ w_as_scratch_register_comma();
+ w_as_register_newline (d_reg);
+ } else {
+ w_as_opcode ("smmla");
+ w_as_scratch_register_comma();
+ w_as_scratch_register_comma();
+ w_as_register_comma (d_reg);
+ w_as_register_newline (d_reg);
+ }
+ if (i>=0){
+ w_as_opcode ("add");
+ w_as_register_comma (d_reg);
+ w_as_scratch_register_comma();
+ w_as_lsr_register_newline (d_reg,31);
+ } else {
+ w_as_opcode ("sub");
+ w_as_register_comma (d_reg);
+ w_as_scratch_register_comma();
+ w_as_register (d_reg);
+ fprintf (assembly_file,",asr #%d",31);
+ w_as_newline_after_instruction();
+ }
+ }
+ } else {
+ if (ms.m>=0){
+ w_as_opcode ("smmul");
+ w_as_scratch_register_comma();
+ w_as_scratch_register_comma();
+ w_as_register_newline (d_reg);
+ } else {
+ w_as_opcode ("smmla");
+ w_as_scratch_register_comma();
+ w_as_scratch_register_comma();
+ w_as_register_comma (d_reg);
+ w_as_register_newline (d_reg);
+ }
+ if (i>=0){
+ w_as_opcode ("lsr");
+ w_as_register_comma (d_reg);
+ w_as_register_comma (d_reg);
+ w_as_immediate_newline (31);
+
+ w_as_opcode ("add");
+ w_as_register_comma (d_reg);
+ w_as_register_comma (d_reg);
+ w_as_scratch_register();
+ fprintf (assembly_file,",asr #%d",ms.s);
+ w_as_newline_after_instruction();
+ } else {
+ w_as_opcode ("asr");
+ w_as_register_comma (d_reg);
+ w_as_register_comma (d_reg);
+ w_as_immediate_newline (31);
+
+ w_as_opcode ("sub");
+ w_as_register_comma (d_reg);
+ w_as_register_comma (d_reg);
+ w_as_scratch_register();
+ fprintf (assembly_file,",asr #%d",ms.s);
+ w_as_newline_after_instruction();
+ }
+ }
+}
+
+static void w_as_rem_instruction (struct instruction *instruction)
+{
+ int i,d_reg;
+ struct ms ms;
+
+ d_reg=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ if (instruction->instruction_parameters[0].parameter_type!=P_IMMEDIATE){
+ internal_error_in_function ("w_as_rem_instruction");
+ return;
+ }
+ i=instruction->instruction_parameters[0].parameter_data.i;
+
+ if (i==0){
+ internal_error_in_function ("w_as_rem_instruction");
+ return;
+ }
+
+ i=abs (i);
+
+ if ((i & (i-1))==0){
+ int log2i;
+ unsigned int i2;
+
+ if (i==1){
+ w_as_ld_immediate (0,d_reg);
+ return;
+ }
+
+ w_as_opcode ("sub");
+ w_as_scratch_register_comma();
+ w_as_register_comma (d_reg);
+ w_as_lsr_register_newline (d_reg,31);
+
+ log2i=0;
+ i2=i;
+ while (i2>1){
+ i2>>=1;
+ ++log2i;
+ }
+
+ if (i<=256){
+ if (log2i!=1){
+ w_as_opcode ("asr");
+ w_as_register_comma (d_reg);
+ w_as_register_comma (d_reg);
+ w_as_immediate_newline (log2i-1);
+ }
+ w_as_opcode ("and");
+ w_as_scratch_register_comma();
+ w_as_scratch_register_comma();
+ w_as_immediate_newline (i-1);
+ } else {
+ w_as_ld_immediate (-1,REGISTER_S1);
+
+ w_as_opcode ("asr");
+ w_as_register_comma (d_reg);
+ w_as_register_comma (d_reg);
+ w_as_immediate_newline (log2i-1);
+
+ w_as_opcode ("and");
+ w_as_scratch_register_comma();
+ w_as_scratch_register_comma();
+ w_as_lsr_register_newline (REGISTER_S1,32-log2i);
+ }
+
+ w_as_opcode ("sub");
+ w_as_register_comma (d_reg);
+ w_as_scratch_register_comma();
+ w_as_lsr_register_newline (d_reg,32-log2i);
+
+ return;
+ }
+
+
+ ms=magic (i);
+
+ w_as_ld_immediate (ms.m,REGISTER_S0);
+
+ if (ms.s==0){
+ if (ms.m>=0){
+ w_as_opcode ("lsr");
+ w_as_register_comma (REGISTER_S1);
+ w_as_register_comma (d_reg);
+ w_as_immediate_newline (31);
+
+ w_as_opcode ("smmla");
+ w_as_scratch_register_comma();
+ w_as_register_comma (d_reg);
+ w_as_scratch_register_comma();
+ w_as_register_newline (REGISTER_S1);
+ } else {
+ if (ms.m>=0){
+ w_as_opcode ("smmul");
+ w_as_scratch_register_comma();
+ w_as_scratch_register_comma();
+ w_as_register_newline (d_reg);
+ } else {
+ w_as_opcode ("smmla");
+ w_as_scratch_register_comma();
+ w_as_scratch_register_comma();
+ w_as_register_comma (d_reg);
+ w_as_register_newline (d_reg);
+ }
+
+ w_as_opcode ("add");
+ w_as_scratch_register_comma();
+ w_as_scratch_register_comma();
+ w_as_lsr_register_newline (d_reg,31);
+ }
+ } else {
+ if (ms.m>=0){
+ w_as_opcode ("smmul");
+ w_as_scratch_register_comma();
+ w_as_scratch_register_comma();
+ w_as_register_newline (d_reg);
+ } else {
+ w_as_opcode ("smmla");
+ w_as_scratch_register_comma();
+ w_as_scratch_register_comma();
+ w_as_register_comma (d_reg);
+ w_as_register_newline (d_reg);
+ }
+
+ w_as_opcode ("lsr");
+ w_as_register_comma (REGISTER_S1);
+ w_as_register_comma (d_reg);
+ w_as_immediate_newline (31);
+
+ w_as_opcode ("add");
+ w_as_scratch_register_comma();
+ w_as_register_comma (REGISTER_S1);
+ w_as_scratch_register();
+ fprintf (assembly_file,",asr #%d",ms.s);
+ w_as_newline_after_instruction();
+ }
+
+ {
+ unsigned int i2;
+
+ i2=i & (i-1);
+ if ((i2 & (i2-1))==0){
+ unsigned int n;
+ int n_shifts;
+
+ n=i;
+
+ n_shifts=0;
+ while (n>0){
+ while ((n & 1)==0){
+ n>>=1;
+ ++n_shifts;
+ }
+
+ w_as_opcode ("sub");
+ w_as_register_comma (d_reg);
+ w_as_register_comma (d_reg);
+ w_as_lsl_register_newline (REGISTER_S0,n_shifts);
+
+ n>>=1;
+ n_shifts=1;
+ }
+ } else {
+#if 1
+ w_as_ld_immediate (-i,REGISTER_S1);
+
+ w_as_opcode ("mla");
+ w_as_register_comma (d_reg);
+ w_as_register_comma (REGISTER_S0);
+ w_as_register_comma (REGISTER_S1);
+ w_as_register_newline (d_reg);
+#else
+ /* mls is an illegal instruction on the raspberry pi b+ */
+ w_as_ld_immediate (i,REGISTER_S1);
+
+ w_as_opcode ("mls");
+ w_as_register_comma (d_reg);
+ w_as_register_comma (REGISTER_S0);
+ w_as_register_comma (REGISTER_S1);
+ w_as_register_newline (d_reg);
+#endif
+ }
+ }
+}
+
+static void w_as_word_instruction (struct instruction *instruction)
+{
+ fprintf (assembly_file,"\t.byte\t%d\n",
+ (int)instruction->instruction_parameters[0].parameter_data.i);
+}
+
+static void w_as_float_constant (int label_number,DOUBLE *r_p)
+{
+ struct float_constant *new_float_constant;
+
+ new_float_constant=allocate_memory_from_heap (sizeof (struct float_constant));
+
+ new_float_constant->float_constant_r_p=r_p;
+ new_float_constant->float_constant_label_number=label_number;
+
+ *float_constant_l=new_float_constant;
+ float_constant_l=&new_float_constant->float_constant_next;
+
+ new_float_constant->float_constant_next=NULL;
+}
+
+static void w_as_fld_parameter (struct parameter *parameter_p)
+{
+ switch (parameter_p->parameter_type){
+ case P_F_IMMEDIATE:
+ {
+ int label_number;
+
+ label_number=next_label_id++;
+
+ w_as_opcode ("fldd");
+ w_as_fp_register_comma (15);
+ fprintf (assembly_file,"i_%d",label_number);
+ w_as_newline_after_instruction();
+ w_as_float_constant (label_number,parameter_p->parameter_data.r);
+ return;
+ }
+ case P_INDIRECT:
+ w_as_opcode ("fldd");
+ w_as_fp_register_comma (15);
+ w_as_indirect_newline (parameter_p->parameter_offset,parameter_p->parameter_data.reg.r);
+ return;
+ case P_INDEXED:
+ {
+ int offset;
+
+ offset=parameter_p->parameter_offset;
+
+ w_as_lea_indexed_no_offset_ir (REGISTER_S0,offset,parameter_p->parameter_data.ir);
+
+ w_as_opcode ("fldd");
+ w_as_fp_register_comma (15);
+ w_as_indirect_newline (offset>>2,REGISTER_S0);
+ w_as_newline_after_instruction();
+ return;
+ }
+ default:
+ internal_error_in_function ("w_as_fld_parameter");
+ return;
+ }
+}
+
+static void w_as_dyadic_float_instruction (struct instruction *instruction,char *opcode)
+{
+ int d_freg;
+
+ d_freg=instruction->instruction_parameters[1].parameter_data.reg.r;
+ if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){
+ w_as_opcode (opcode);
+ w_as_fp_register_comma (d_freg);
+ w_as_fp_register_comma (d_freg);
+ w_as_fp_register_newline (instruction->instruction_parameters[0].parameter_data.reg.r);
+ } else {
+ w_as_fld_parameter (&instruction->instruction_parameters[0]);
+
+ w_as_opcode (opcode);
+ w_as_fp_register_comma (d_freg);
+ w_as_fp_register_comma (d_freg);
+ w_as_fp_register_newline (15);
+ }
+}
+
+static void w_as_compare_float_instruction (struct instruction *instruction)
+{
+ if (instruction->instruction_parameters[0].parameter_type!=P_F_REGISTER){
+ if (instruction->instruction_parameters[0].parameter_type==P_F_IMMEDIATE &&
+ ((int*)&instruction->instruction_parameters[0].parameter_data.r)[0]==0 &&
+ ((int*)&instruction->instruction_parameters[0].parameter_data.r)[1]==0)
+ {
+ w_as_opcode ("fcmpzd");
+ w_as_fp_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r);
+ } else {
+ w_as_fld_parameter (&instruction->instruction_parameters[0]);
+
+ w_as_opcode ("fcmpd");
+ w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_fp_register_newline (15);
+ }
+ } else {
+ w_as_opcode ("fcmpd");
+ w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_fp_register_newline (instruction->instruction_parameters[0].parameter_data.reg.r);
+ }
+}
+
+static void w_as_monadic_float_instruction (struct instruction *instruction,char *opcode)
+{
+ int d_freg;
+
+ d_freg=instruction->instruction_parameters[1].parameter_data.reg.r;
+ if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){
+ w_as_opcode (opcode);
+ w_as_fp_register (d_freg);
+ w_as_comma();
+ w_as_fp_register_newline (instruction->instruction_parameters[0].parameter_data.reg.r);
+ } else {
+ w_as_fld_parameter (&instruction->instruction_parameters[0]);
+
+ w_as_opcode (opcode);
+ w_as_fp_register (d_freg);
+ w_as_comma();
+ w_as_fp_register_newline (15);
+ }
+}
+
+static void w_as_fmove_instruction (struct instruction *instruction)
+{
+ switch (instruction->instruction_parameters[1].parameter_type){
+ case P_F_REGISTER:
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_F_REGISTER:
+ w_as_opcode ("fcpyd");
+ w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_fp_register_newline (instruction->instruction_parameters[0].parameter_data.reg.r);
+ return;
+ case P_INDIRECT:
+ w_as_opcode ("fldd");
+ w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_indirect_newline (instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ return;
+ case P_INDEXED:
+ {
+ int offset;
+
+ offset=instruction->instruction_parameters[0].parameter_offset;
+
+ w_as_lea_indexed_no_offset_ir (REGISTER_S0,offset,instruction->instruction_parameters[0].parameter_data.ir);
+
+ w_as_opcode ("fldd");
+ w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_indirect_newline (offset>>2,REGISTER_S0);
+ return;
+ }
+ 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 ("fldd");
+ w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ fprintf (assembly_file,"i_%d",label_number);
+ w_as_newline_after_instruction();
+ return;
+ }
+ default:
+ internal_error_in_function ("w_as_fmove_instruction");
+ return;
+ }
+ case P_INDIRECT:
+ case P_INDEXED:
+ if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){
+ if (instruction->instruction_parameters[1].parameter_type==P_INDIRECT){
+ w_as_opcode ("fstd");
+ w_as_fp_register_comma (instruction->instruction_parameters[0].parameter_data.reg.r);
+ w_as_indirect_newline (instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ } else {
+ int offset;
+
+ offset=instruction->instruction_parameters[1].parameter_offset;
+
+ w_as_lea_indexed_no_offset_ir (REGISTER_S0,offset,instruction->instruction_parameters[1].parameter_data.ir);
+
+ w_as_opcode ("fstd");
+ w_as_fp_register_comma (instruction->instruction_parameters[0].parameter_data.reg.r);
+ w_as_indirect_newline (offset>>2,REGISTER_S0);
+ return;
+ }
+ }
+ }
+ internal_error_in_function ("w_as_fmove_instruction");
+}
+
+static w_as_floads_instruction (struct instruction *instruction)
+{
+ switch (instruction->instruction_parameters[1].parameter_type){
+ case P_F_REGISTER:
+ {
+ int d_freg;
+
+ d_freg=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_INDIRECT:
+ w_as_opcode ("vldr");
+ fprintf (assembly_file,"s%d",d_freg<<1);
+ w_as_indirect_newline (instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ break;
+ case P_INDEXED:
+ {
+ int offset;
+
+ offset=instruction->instruction_parameters[0].parameter_offset;
+
+ w_as_lea_indexed_no_offset_ir (REGISTER_S0,offset,instruction->instruction_parameters[0].parameter_data.ir);
+
+ w_as_opcode ("vldr");
+ fprintf (assembly_file,"s%d",d_freg<<1);
+ w_as_comma();
+ w_as_indirect_newline (offset>>2,REGISTER_S0);
+ break;
+ }
+ default:
+ internal_error_in_function ("w_as_floads_instruction");
+ return;
+ }
+
+ w_as_opcode ("vcvtr.f64.f32");
+ w_as_fp_register_comma (d_freg);
+ fprintf (assembly_file,"s%d",d_freg<<1);
+ w_as_newline_after_instruction();
+ return;
+ }
+ }
+ internal_error_in_function ("w_as_floads_instruction");
+}
+
+static void w_as_fmoves_instruction (struct instruction *instruction)
+{
+ if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){
+ int s_freg;
+
+ s_freg=instruction->instruction_parameters[0].parameter_data.reg.r;
+
+ w_as_opcode ("vcvtr.f32.f64");
+ fprintf (assembly_file,"s%d",s_freg<<1);
+ w_as_comma();
+ w_as_fp_register_newline (15);
+
+ switch (instruction->instruction_parameters[1].parameter_type){
+ case P_INDIRECT:
+ w_as_opcode ("vstr");
+ fprintf (assembly_file,"s%d",15<<1);
+ w_as_comma();
+ w_as_indirect_newline (instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_INDEXED:
+ {
+ int offset;
+
+ offset=instruction->instruction_parameters[0].parameter_offset;
+
+ w_as_lea_indexed_no_offset_ir (REGISTER_S0,offset,instruction->instruction_parameters[0].parameter_data.ir);
+
+ w_as_opcode ("vstr");
+ fprintf (assembly_file,"s%d",15<<1);
+ w_as_comma();
+ w_as_indirect_newline (offset>>2,REGISTER_S0);
+ }
+ return;
+ }
+ }
+ internal_error_in_function ("w_as_fmoves_instruction");
+}
+
+static void w_as_fmovel_instruction (struct instruction *instruction)
+{
+ if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){
+ if (instruction->instruction_parameters[1].parameter_type==P_REGISTER){
+ int s_freg;
+
+ s_freg=instruction->instruction_parameters[0].parameter_data.reg.r;
+
+ w_as_opcode ("vcvtr.s32.f64" /*"ftosid"*/);
+ fprintf (assembly_file,"s%d,d%d",s_freg<<1,s_freg);
+ w_as_newline_after_instruction();
+
+ w_as_opcode ("fmrs");
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ fprintf (assembly_file,"s%d",s_freg<<1);
+ w_as_newline_after_instruction();
+ } else
+ internal_error_in_function ("w_as_fmovel_instruction");
+ } else {
+ int freg;
+
+ freg=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_REGISTER:
+ w_as_opcode ("vmov");
+ fprintf (assembly_file,"s%d",freg<<1);
+ w_as_comma_register (instruction->instruction_parameters[0].parameter_data.reg.r);
+ w_as_newline_after_instruction();
+ break;
+ case P_INDIRECT:
+ w_as_opcode ("ldr");
+ w_as_scratch_register_comma();
+ w_as_indirect_newline (instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+
+ w_as_opcode ("vmov");
+ fprintf (assembly_file,"s%d",freg<<1);
+ w_as_comma_scratch_register_newline();
+ break;
+ case P_INDEXED:
+ w_as_ld_indexed (&instruction->instruction_parameters[0],REGISTER_S0,SIZE_LONG);
+
+ w_as_opcode ("vmov");
+ fprintf (assembly_file,"s%d",freg<<1);
+ w_as_comma_scratch_register_newline();
+ break;
+ case P_IMMEDIATE:
+ /* the assembler does not assemble the following instruction correctly */
+ w_as_opcode ("vldr" /*"flds"*/);
+ fprintf (assembly_file,"s%d,=%d",freg<<1,instruction->instruction_parameters[0].parameter_data.i);
+ w_as_newline_after_instruction();
+ break;
+ default:
+ internal_error_in_function ("w_as_fmovel_instruction");
+ return;
+ }
+
+ w_as_opcode ("vcvt.f64.s32" /*"fsitod"*/);
+ fprintf (assembly_file,"d%d,s%d",freg,freg<<1);
+ w_as_newline_after_instruction();
+ return;
+ }
+}
+
+static void w_as_rts_instruction (void)
+{
+ w_as_opcode ("ldr");
+ fprintf (assembly_file,"pc,[sp],#4");
+ w_as_newline_after_instruction();
+
+ write_float_constants();
+ w_as_opcode (".ltorg");
+ w_as_newline();
+ instruction_n_after_ltorg = 0u;
+ ltorg_at_instruction_n = 0u-1u;
+}
+
+static void w_as_rtsp_instruction (void)
+{
+ w_as_opcode ("b");
+ w_as_label ("profile_r");
+ w_as_newline_after_instruction();
+}
+
+static void w_as_instructions (register struct instruction *instruction)
+{
+ while (instruction!=NULL){
+ switch (instruction->instruction_icode){
+ case IMOVE:
+ w_as_move_instruction (instruction,SIZE_LONG);
+ break;
+ case ILEA:
+ w_as_lea_instruction (instruction);
+ break;
+ case IADD:
+ w_as_dyadic_instruction (instruction,"add");
+ break;
+ case ISUB:
+ w_as_dyadic_instruction (instruction,"sub");
+ break;
+ case ICMP:
+ w_as_cmp_instruction (instruction);
+ break;
+ case IJMP:
+ w_as_jmp_instruction (instruction);
+ break;
+ case IJMPP:
+ w_as_jmpp_instruction (instruction);
+ break;
+ case IJSR:
+ w_as_jsr_instruction (instruction);
+ break;
+ case IRTS:
+ w_as_rts_instruction();
+ break;
+ case IRTSP:
+ w_as_rtsp_instruction();
+ break;
+ case IBEQ:
+ w_as_branch_instruction (instruction,"beq");
+ break;
+ case IBGE:
+ w_as_branch_instruction (instruction,"bge");
+ break;
+ case IBGEU:
+ w_as_branch_instruction (instruction,"bhs");
+ break;
+ case IBGT:
+ w_as_branch_instruction (instruction,"bgt");
+ break;
+ case IBGTU:
+ w_as_branch_instruction (instruction,"bhi");
+ break;
+ case IBLE:
+ w_as_branch_instruction (instruction,"ble");
+ break;
+ case IBLEU:
+ w_as_branch_instruction (instruction,"bls");
+ break;
+ case IBLT:
+ w_as_branch_instruction (instruction,"blt");
+ break;
+ case IBLTU:
+ w_as_branch_instruction (instruction,"blo");
+ break;
+ case IBNE:
+ w_as_branch_instruction (instruction,"bne");
+ break;
+ case IBO:
+ w_as_branch_instruction (instruction,"bvs");
+ break;
+ case IBNO:
+ w_as_branch_instruction (instruction,"bvc");
+ break;
+ case ILSL:
+ w_as_shift_instruction (instruction,"lsl");
+ break;
+ case ILSR:
+ w_as_shift_instruction (instruction,"lsr");
+ break;
+ case IASR:
+ w_as_shift_instruction (instruction,"asr");
+ break;
+ case IMUL:
+ w_as_mul_instruction (instruction);
+ break;
+ case IDIV:
+ w_as_div_instruction (instruction);
+ break;
+ case IREM:
+ w_as_rem_instruction (instruction);
+ break;
+ case IAND:
+ w_as_dyadic_instruction (instruction,"and");
+ break;
+ case IOR:
+ w_as_dyadic_instruction (instruction,"orr");
+ break;
+ case IEOR:
+ w_as_dyadic_instruction (instruction,"eor");
+ break;
+ case IADDI:
+ w_as_reg_reg_imm_instruction (instruction,"add");
+ break;
+ case ILSLI:
+ w_as_reg_reg_imm_instruction (instruction,"lsl");
+ break;
+ case ISEQ:
+ w_as_set_condition_instruction (instruction,"moveq","movne");
+ break;
+ case ISGE:
+ w_as_set_condition_instruction (instruction,"movge","movlt");
+ break;
+ case ISGEU:
+ w_as_set_condition_instruction (instruction,"movhs","movlo");
+ break;
+ case ISGT:
+ w_as_set_condition_instruction (instruction,"movgt","movle");
+ break;
+ case ISGTU:
+ w_as_set_condition_instruction (instruction,"movhi","movls");
+ break;
+ case ISLE:
+ w_as_set_condition_instruction (instruction,"movle","movgt");
+ break;
+ case ISLEU:
+ w_as_set_condition_instruction (instruction,"movls","movhi");
+ break;
+ case ISLT:
+ w_as_set_condition_instruction (instruction,"movlt","movge");
+ break;
+ case ISLTU:
+ w_as_set_condition_instruction (instruction,"movlo","movhs");
+ break;
+ case ISNE:
+ w_as_set_condition_instruction (instruction,"movne","moveq");
+ break;
+ case ISO:
+ w_as_set_condition_instruction (instruction,"movvs","movvc");
+ break;
+ case ISNO:
+ w_as_set_condition_instruction (instruction,"movvc","movvs");
+ break;
+ case ITST:
+ w_as_tst_instruction (instruction);
+ break;
+ case IBTST:
+ w_as_btst_instruction (instruction);
+ break;
+ case IMOVEDB:
+ w_as_move_instruction (instruction,SIZE_WORD);
+ break;
+ case IMOVEB:
+ w_as_move_instruction (instruction,SIZE_BYTE);
+ break;
+ case INEG:
+ w_as_monadic_instruction (instruction,"neg");
+ break;
+ case INOT:
+ w_as_monadic_instruction (instruction,"mvn");
+ break;
+ case IMOVEM:
+ w_as_movem_instruction (instruction);
+ break;
+ case IADC:
+ w_as_dyadic_instruction (instruction,"adcl");
+ break;
+ case ISBB:
+ w_as_dyadic_instruction (instruction,"sbbl");
+ break;
+ case IROTR:
+ w_as_shift_instruction (instruction,"ror");
+ break;
+ case IADDO:
+ w_as_dyadic_instruction (instruction,"adds");
+ break;
+ case ISUBO:
+ w_as_dyadic_instruction (instruction,"subs");
+ break;
+ case IFMOVE:
+ w_as_fmove_instruction (instruction);
+ break;
+ case IFADD:
+ w_as_dyadic_float_instruction (instruction,"faddd");
+ break;
+ case IFSUB:
+ w_as_dyadic_float_instruction (instruction,"fsubd");
+ break;
+ case IFCMP:
+ w_as_compare_float_instruction (instruction);
+ break;
+ case IFDIV:
+ w_as_dyadic_float_instruction (instruction,"fdivd");
+ break;
+ case IFMUL:
+ w_as_dyadic_float_instruction (instruction,"fmuld");
+ break;
+ case IFBEQ:
+ w_as_float_branch_instruction (instruction,"beq");
+ break;
+ case IFBGE:
+ w_as_float_branch_instruction (instruction,"bpl");
+ break;
+ case IFBGT:
+ w_as_float_branch_instruction (instruction,"bgt");
+ break;
+ case IFBLE:
+ w_as_float_branch_instruction (instruction,"ble");
+ break;
+ case IFBLT:
+ w_as_float_branch_instruction (instruction,"bmi");
+ break;
+ case IFBNE:
+ w_as_float_branch_instruction (instruction,"bne");
+ break;
+ case IFMOVEL:
+ w_as_fmovel_instruction (instruction);
+ break;
+ case IFLOADS:
+ w_as_floads_instruction (instruction);
+ break;
+ case IFMOVES:
+ w_as_fmoves_instruction (instruction);
+ break;
+ case IFSQRT:
+ w_as_monadic_float_instruction (instruction,"fsqrtd");
+ break;
+ case IFNEG:
+ w_as_monadic_float_instruction (instruction,"fnegd");
+ break;
+ case IFABS:
+ w_as_monadic_float_instruction (instruction,"fabsd");
+ break;
+ case IFSEQ:
+ w_as_set_float_condition_instruction (instruction,"moveq","movne");
+ break;
+ case IFSGE:
+ w_as_set_float_condition_instruction (instruction,"bpl","bmi");
+ break;
+ case IFSGT:
+ w_as_set_float_condition_instruction (instruction,"movgt","movle");
+ break;
+ case IFSLE:
+ w_as_set_float_condition_instruction (instruction,"movle","movgt");
+ break;
+ case IFSLT:
+ w_as_set_float_condition_instruction (instruction,"bmi","bpl");
+ break;
+ case IFSNE:
+ w_as_set_float_condition_instruction (instruction,"movne","moveq");
+ break;
+ case IWORD:
+ w_as_word_instruction (instruction);
+ break;
+ case IFTST:
+ default:
+ internal_error_in_function ("w_as_instructions");
+ }
+ instruction=instruction->instruction_next;
+ }
+}
+
+static void w_as_number_of_arguments (int n_node_arguments)
+{
+ w_as_opcode (".long");
+ fprintf (assembly_file,"%d",n_node_arguments);
+ w_as_newline();
+}
+
+struct call_and_jump {
+ struct call_and_jump *cj_next;
+ WORD cj_label_id;
+ WORD cj_jump_id;
+ char *cj_call_label_name;
+};
+
+static struct call_and_jump *first_call_and_jump,*last_call_and_jump;
+
+static void w_as_garbage_collect_test (register struct basic_block *block)
+{
+ LONG n_cells;
+ int label_id_1,label_id_2;
+ struct call_and_jump *new_call_and_jump;
+
+ n_cells=block->block_n_new_heap_cells;
+
+ label_id_1=next_label_id++;
+ label_id_2=next_label_id++;
+
+ new_call_and_jump=allocate_memory_from_heap (sizeof (struct call_and_jump));
+
+ new_call_and_jump->cj_next=NULL;
+ new_call_and_jump->cj_label_id=label_id_1;
+ new_call_and_jump->cj_jump_id=label_id_2;
+
+ switch (block->block_n_begin_a_parameter_registers){
+ case 0:
+ new_call_and_jump->cj_call_label_name="collect_0";
+ break;
+ case 1:
+ new_call_and_jump->cj_call_label_name="collect_1";
+ break;
+ case 2:
+ new_call_and_jump->cj_call_label_name="collect_2";
+ break;
+ case 3:
+ new_call_and_jump->cj_call_label_name="collect_3";
+ break;
+ default:
+ internal_error_in_function ("w_as_garbage_collect_test");
+ return;
+ }
+
+ if (first_call_and_jump!=NULL)
+ last_call_and_jump->cj_next=new_call_and_jump;
+ else
+ first_call_and_jump=new_call_and_jump;
+ last_call_and_jump=new_call_and_jump;
+
+ if (mov_or_mvn_immediate (n_cells)){
+ w_as_opcode ("subs");
+ fprintf (assembly_file,"r5,r5,#%d",n_cells);
+ w_as_newline_after_instruction();
+ } else {
+ if (instruction_n_after_ltorg+MAX_LITERAL_INSTRUCTION_OFFSET < ltorg_at_instruction_n)
+ ltorg_at_instruction_n = instruction_n_after_ltorg+MAX_LITERAL_INSTRUCTION_OFFSET;
+
+ w_as_opcode ("ldr");
+ w_as_scratch_register_comma();
+ fprintf (assembly_file,"=%d",n_cells);
+ w_as_newline_after_instruction();
+
+ w_as_opcode ("subs");
+ fputs ("r5,r5",assembly_file);
+ w_as_comma_scratch_register_newline();
+ }
+
+ w_as_opcode ("blo");
+ w_as_internal_label (label_id_1);
+ w_as_newline_after_instruction ();
+
+ w_as_define_internal_label (label_id_2);
+}
+
+static void w_as_call_and_jump (struct call_and_jump *call_and_jump)
+{
+ w_as_define_internal_label (call_and_jump->cj_label_id);
+
+ w_as_opcode ("bl");
+ w_as_label (call_and_jump->cj_call_label_name);
+ w_as_newline_after_instruction();
+
+ w_as_opcode ("b");
+ w_as_internal_label (call_and_jump->cj_jump_id);
+ w_as_newline_after_instruction();
+}
+
+static void w_as_labels (register struct block_label *labels)
+{
+ for (; labels!=NULL; labels=labels->block_label_next)
+ if (labels->block_label_label->label_number==0)
+ w_as_define_code_label (labels->block_label_label);
+ else
+ w_as_define_local_label (labels->block_label_label->label_number);
+}
+
+static void w_as_check_stack (struct basic_block *block)
+{
+ if (block->block_a_stack_check_size>0){
+ if (block->block_a_stack_check_size<=32){
+ w_as_opcode ("cmpl");
+ fprintf (assembly_file,end_a_stack_label->label_name);
+ w_as_comma_register (A_STACK_POINTER);
+ } else {
+ w_as_opcode ("leal");
+ w_as_indirect (block->block_a_stack_check_size,A_STACK_POINTER);
+ w_as_comma_scratch_register();
+ w_as_newline_after_instruction();
+
+ w_as_opcode ("cmpl");
+ fprintf (assembly_file,end_a_stack_label->label_name);
+ w_as_comma_scratch_register();
+ }
+ w_as_newline_after_instruction();
+
+ w_as_opcode ("bhs");
+ w_as_label (stack_overflow_label->label_name);
+ w_as_newline_after_instruction();
+ }
+
+ if (block->block_b_stack_check_size>0){
+ if (block->block_b_stack_check_size<=32){
+ w_as_opcode ("cmpl");
+ fprintf (assembly_file,end_b_stack_label->label_name);
+ w_as_comma_register (B_STACK_POINTER);
+ } else {
+ w_as_opcode ("leal");
+ w_as_indirect (block->block_b_stack_check_size,B_STACK_POINTER);
+ w_as_comma_scratch_register();
+ w_as_newline_after_instruction();
+
+ w_as_opcode ("cmpl");
+ fprintf (assembly_file,end_b_stack_label->label_name);
+ w_as_comma_scratch_register();
+ }
+ w_as_newline_after_instruction();
+
+ w_as_opcode ("jb");
+ w_as_label (stack_overflow_label->label_name);
+ w_as_newline_after_instruction();
+ }
+}
+
+void initialize_write_assembly (FILE *ass_file)
+{
+ assembly_file=ass_file;
+
+ in_data_section=0;
+
+ first_call_and_jump=NULL;
+}
+
+extern LABEL *eval_fill_label,*eval_upd_labels[];
+
+static void w_as_node_entry_info (struct basic_block *block)
+{
+ if (block->block_ea_label!=NULL){
+ int n_node_arguments;
+
+ n_node_arguments=block->block_n_node_arguments;
+ if (n_node_arguments<-2)
+ n_node_arguments=1;
+
+ if (n_node_arguments>=0 && block->block_ea_label!=eval_fill_label){
+ if (!block->block_profile){
+ w_as_opcode ("ldr");
+ w_as_register_comma (REGISTER_A3);
+ w_as_immediate_label_name (block->block_ea_label->label_name);
+ w_as_newline();
+
+ w_as_opcode ("b");
+ w_as_label (eval_upd_labels[n_node_arguments]->label_name);
+ w_as_newline();
+
+ w_as_instruction_without_parameters ("nop");
+ } else {
+ w_as_opcode_mov();
+ w_as_immediate_label_name (block->block_ea_label->label_name);
+ w_as_comma_register (REGISTER_D0);
+ w_as_newline();
+
+ w_as_opcode_mov();
+ w_as_descriptor (block->block_profile_function_label,0);
+ w_as_comma_register (REGISTER_A3);
+ w_as_newline();
+
+ w_as_opcode ("b");
+ w_as_label (eval_upd_labels[n_node_arguments]->label_name);
+ fprintf (assembly_file,"-7");
+ w_as_newline();
+ }
+ } else {
+ w_as_opcode ("b");
+ w_as_label (block->block_ea_label->label_name);
+ w_as_newline();
+
+ w_as_space (8);
+ }
+
+ if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag || module_info_flag))
+ w_as_label_in_code_section (block->block_descriptor->label_name);
+ else
+ w_as_number_of_arguments (0);
+ } else
+ if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag || module_info_flag))
+ w_as_label_in_code_section (block->block_descriptor->label_name);
+
+ w_as_number_of_arguments (block->block_n_node_arguments);
+}
+
+static void w_as_profile_call (struct basic_block *block)
+{
+ w_as_opcode_mov();
+ w_as_descriptor (block->block_profile_function_label,0);
+ w_as_comma_scratch_register();
+ w_as_newline_after_instruction();
+
+ w_as_opcode ("call");
+
+ if (block->block_n_node_arguments>-100)
+ w_as_label (block->block_profile==2 ? "profile_n2" : "profile_n");
+ else {
+ switch (block->block_profile){
+ case 2: w_as_label ("profile_s2"); break;
+ case 4: w_as_label ("profile_l"); break;
+ case 5: w_as_label ("profile_l2"); break;
+ default: w_as_label ("profile_s");
+ }
+ }
+ w_as_newline_after_instruction();
+}
+
+#ifdef NEW_APPLY
+extern LABEL *add_empty_node_labels[];
+
+static void w_as_apply_update_entry (struct basic_block *block)
+{
+ if (block->block_profile)
+ w_as_profile_call (block);
+
+ if (block->block_n_node_arguments==-200){
+ w_as_opcode ("b");
+ w_as_label (block->block_ea_label->label_name);
+ w_as_newline();
+
+ w_as_instruction_without_parameters ("nop");
+ } else {
+ w_as_opcode ("bl");
+ w_as_label (add_empty_node_labels[block->block_n_node_arguments+200]->label_name);
+ w_as_newline();
+
+ w_as_opcode ("b");
+ w_as_label (block->block_ea_label->label_name);
+ w_as_newline();
+ }
+}
+#endif
+
+void write_assembly (VOID)
+{
+ struct basic_block *block;
+ struct call_and_jump *call_and_jump;
+
+ instruction_n_after_ltorg = 0u;
+ ltorg_at_instruction_n = 0u-1u;
+
+ fprintf (assembly_file,"\t.fpu\tvfp");
+ w_as_newline();
+
+ w_as_to_code_section();
+
+ float_constant_l=&first_float_constant;
+ first_float_constant=NULL;
+
+ for_l (block,first_block,block_next){
+ if (block->block_n_node_arguments>-100){
+ w_as_align (2);
+ w_as_node_entry_info (block);
+ }
+#ifdef NEW_APPLY
+ else if (block->block_n_node_arguments<-100)
+ w_as_apply_update_entry (block);
+#endif
+
+ w_as_labels (block->block_labels);
+
+ if (block->block_profile)
+ w_as_profile_call (block);
+
+ if (block->block_n_new_heap_cells>0)
+ w_as_garbage_collect_test (block);
+
+ if (check_stack && (block->block_a_stack_check_size>0 || block->block_b_stack_check_size>0))
+ w_as_check_stack (block);
+
+ w_as_instructions (block->block_instructions);
+ }
+
+ for_l (call_and_jump,first_call_and_jump,cj_next)
+ w_as_call_and_jump (call_and_jump);
+
+ write_float_constants();
+}