summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgpas.c4446
-rw-r--r--cgpwas.c3421
2 files changed, 7867 insertions, 0 deletions
diff --git a/cgpas.c b/cgpas.c
new file mode 100644
index 0000000..d4fa2bd
--- /dev/null
+++ b/cgpas.c
@@ -0,0 +1,4446 @@
+/*
+ File: cgpas.c
+ Author: John van Groningen
+ Copyright: University of Nijmegen
+ Machine: Power Macintosh
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "cgport.h"
+
+#ifdef G_POWER
+
+#if defined (LINUX_ELF)
+# define ELF
+# include <elf.h>
+#elif defined (PROJECT_BUILDER) || defined (MACH_O)
+# define G_MACH_O
+# include </usr/include/mach-o/loader.h>
+# include </usr/include/mach-o/nlist.h>
+# include </usr/include/mach-o/ppc/reloc.h>
+#else
+# define XCOFF
+#endif
+
+#define for_l(v,l,n) for(v=(l);v!=NULL;v=v->n)
+
+#undef USE_DCBZ
+
+#define FSUB_FDIV_REVERSED
+#define TRL_RELOCATIONS
+
+#include "cgrconst.h"
+#include "cgtypes.h"
+#include "cg.h"
+#include "cgiconst.h"
+#include "cgcode.h"
+#include "cginstructions.h"
+#include "cgpas.h"
+#include "cgptoc.h"
+
+#define IO_BUFFER_SIZE 16384
+#define BUFFER_SIZE 4096
+
+struct object_buffer {
+ struct object_buffer * next;
+ int size;
+ unsigned char data [BUFFER_SIZE];
+};
+
+#define CONDITIONAL_BRANCH_RELOCATION 0
+#define BRANCH_RELOCATION 1
+#ifndef ELF
+# define TOC_RELOCATION 2
+#endif
+#define LONG_WORD_RELOCATION 3
+#define DUMMY_CONDITIONAL_BRANCH_RELOCATION 4
+#ifdef XCOFF
+# define TRL_RELOCATION 5
+#endif
+#if defined (ELF) || defined (G_MACH_O)
+# define HIGH_RELOCATION 6
+# define LOW_RELOCATION 7
+#endif
+
+struct relocation {
+ struct relocation * next;
+ unsigned long offset;
+ struct object_label * relocation_object_label;
+ union {
+ struct label * u_label;
+#define relocation_label relocation_u.u_label
+ struct toc_label * u_toc_label;
+#define relocation_toc_label relocation_u.u_toc_label
+ } relocation_u;
+#if defined (ELF) || defined (G_MACH_O)
+ long relocation_addend;
+#endif
+ short kind;
+};
+
+static struct relocation *first_code_relocation,**last_code_relocation_l;
+static struct relocation *first_data_relocation,**last_data_relocation_l;
+static int n_code_relocations,n_data_relocations;
+
+static struct object_buffer *first_code_buffer,*current_code_buffer;
+static int code_buffer_free,code_buffer_offset;
+static unsigned int *code_buffer_p;
+
+static struct object_buffer *first_data_buffer,*current_data_buffer;
+static int data_buffer_free,data_buffer_offset;
+static unsigned int *data_buffer_p;
+
+static void initialize_buffers (void)
+{
+ struct object_buffer *new_code_buffer,*new_data_buffer;
+
+ new_code_buffer=memory_allocate_type (struct object_buffer);
+
+ new_code_buffer->size=0;
+ new_code_buffer->next=NULL;
+
+ first_code_buffer=new_code_buffer;
+ current_code_buffer=new_code_buffer;
+ code_buffer_offset=0;
+
+ code_buffer_free=BUFFER_SIZE;
+ code_buffer_p=(unsigned int*)new_code_buffer->data;
+
+ new_data_buffer=memory_allocate_type (struct object_buffer);
+
+ new_data_buffer->size=0;
+ new_data_buffer->next=NULL;
+
+ first_data_buffer=new_data_buffer;
+ current_data_buffer=new_data_buffer;
+ data_buffer_offset=0;
+
+ data_buffer_free=BUFFER_SIZE;
+ data_buffer_p=(unsigned int*)new_data_buffer->data;
+}
+
+static void store_instruction2 (int c)
+{
+ struct object_buffer *new_buffer;
+
+ current_code_buffer->size=BUFFER_SIZE;
+
+ new_buffer=memory_allocate_type (struct object_buffer);
+
+ new_buffer->size=0;
+ new_buffer->next=NULL;
+
+ current_code_buffer->next=new_buffer;
+ current_code_buffer=new_buffer;
+ code_buffer_offset+=BUFFER_SIZE;
+
+ code_buffer_free=BUFFER_SIZE-4;
+ code_buffer_p=(unsigned int*)new_buffer->data;
+
+ *code_buffer_p++=c;
+}
+
+static void store_instruction (int c)
+{
+ if (code_buffer_free>=4){
+ code_buffer_free-=4;
+ *code_buffer_p++=c;
+ } else
+ store_instruction2 (c);
+}
+
+static void store_long_word_in_data_section2 (ULONG c)
+{
+ struct object_buffer *new_buffer;
+
+ current_data_buffer->size=BUFFER_SIZE;
+
+ new_buffer=memory_allocate_type (struct object_buffer);
+
+ new_buffer->size=0;
+ new_buffer->next=NULL;
+
+ current_data_buffer->next=new_buffer;
+ current_data_buffer=new_buffer;
+ data_buffer_offset+=BUFFER_SIZE;
+
+ data_buffer_free=BUFFER_SIZE-4;
+ data_buffer_p=(unsigned int*)new_buffer->data;
+
+ *data_buffer_p++=c;
+}
+
+void store_long_word_in_data_section (ULONG c)
+{
+ if (data_buffer_free>=4){
+ data_buffer_free-=4;
+ *data_buffer_p++=c;
+ } else
+ store_long_word_in_data_section2 (c);
+}
+
+void store_2_words_in_data_section (UWORD w1,UWORD w2)
+{
+ store_long_word_in_data_section ((w1<<16) | ((UWORD)w2));
+}
+
+static void flush_code_buffer (void)
+{
+ current_code_buffer->size=BUFFER_SIZE-code_buffer_free;
+ code_buffer_offset+=BUFFER_SIZE-code_buffer_free;
+}
+
+static void flush_data_buffer (void)
+{
+ current_data_buffer->size=BUFFER_SIZE-data_buffer_free;
+ data_buffer_offset+=BUFFER_SIZE-data_buffer_free;
+}
+
+static FILE *output_file;
+
+static void write_buffers_and_release_memory (struct object_buffer **first_buffer_l)
+{
+ struct object_buffer *buffer,*next_buffer;
+
+ for (buffer=*first_buffer_l; buffer!=NULL; buffer=next_buffer){
+ int size;
+
+ size=buffer->size;
+
+ if (fwrite (buffer->data,1,size,output_file)!=size)
+ error ("Write error");
+
+ next_buffer=buffer->next;
+
+ memory_free (buffer);
+ }
+
+ *first_buffer_l=NULL;
+}
+
+void store_abc_string_in_data_section (char *string,int length)
+{
+ unsigned char *string_p;
+
+ string_p=(unsigned char*)string;
+ store_long_word_in_data_section (length);
+
+ while (length>=4){
+ store_long_word_in_data_section (*(ULONG*)string_p);
+ string_p+=4;
+ length-=4;
+ }
+
+ if (length>0){
+ ULONG d;
+ int shift;
+
+ d=0;
+ shift=24;
+ while (length>0){
+ d |= string_p[0]<<shift;
+ shift-=8;
+ --length;
+ ++string_p;
+ }
+ store_long_word_in_data_section (d);
+ }
+}
+
+void store_c_string_in_data_section (char *string,int length)
+{
+ unsigned char *string_p;
+ ULONG d;
+ int shift;
+
+ string_p=(unsigned char*)string;
+
+ while (length>=4){
+ store_long_word_in_data_section (*(ULONG*)string_p);
+ string_p+=4;
+ length-=4;
+ }
+
+ d=0;
+ shift=24;
+ while (length>0){
+ d |= string_p[0]<<shift;
+ shift-=8;
+ --length;
+ ++string_p;
+ }
+ store_long_word_in_data_section (d);
+}
+
+#define CURRENT_CODE_OFFSET (code_buffer_offset+((unsigned char*)code_buffer_p-current_code_buffer->data))
+#define CURRENT_DATA_OFFSET (data_buffer_offset+((unsigned char*)data_buffer_p-current_data_buffer->data))
+
+static void store_label_plus_offset_in_data_section (LABEL *label,int offset)
+{
+ struct relocation *new_relocation;
+
+#ifdef G_MACH_O
+ store_long_word_in_data_section (0);
+#else
+ store_long_word_in_data_section (offset);
+#endif
+
+ new_relocation=fast_memory_allocate_type (struct relocation);
+ ++n_data_relocations;
+
+ *last_data_relocation_l=new_relocation;
+ last_data_relocation_l=&new_relocation->next;
+ new_relocation->next=NULL;
+
+ new_relocation->relocation_label=label;
+ new_relocation->offset=CURRENT_DATA_OFFSET-4;
+ new_relocation->kind=LONG_WORD_RELOCATION;
+#if defined (ELF) || defined (G_MACH_O)
+ new_relocation->relocation_addend=offset;
+#endif
+}
+
+void store_label_in_data_section (LABEL *label)
+{
+ store_label_plus_offset_in_data_section (label,0);
+}
+
+void store_descriptor_in_data_section (LABEL *label)
+{
+ store_label_plus_offset_in_data_section (label,2);
+}
+
+#define CODE_CONTROL_SECTION 0
+#define DATA_CONTROL_SECTION 1
+#define IMPORTED_CODE_LABEL 2
+#define EXPORTED_CODE_LABEL 3
+#define EXPORTED_DATA_LABEL 4
+#define MERGED_CODE_CONTROL_SECTION 5
+#ifdef G_MACH_O
+# define STUB_CONTROL_SECTION 6
+#endif
+
+struct object_label {
+ struct object_label * next;
+ union {
+ unsigned long offset; /* CODE_CONTROL_SECTION,DATA_CONTROL_SECTION */
+ struct label * label; /* IMPORTED_CODE_LABEL,EXPORTED_CODE_LABEL */
+ } object_label_u1;
+ union {
+ long reference; /* CODE_CONTROL_SECTION,DATA_CONTROL_SECTION */
+ unsigned long size; /* CODE_CONTROL_SECTION,DATA_CONTROL_SECTION */
+ unsigned long string_offset; /* IMPORTED_CODE_LABEL,EXPORTED_CODE_LABEL */
+ } object_label_u2;
+ int object_label_number;
+ short kind;
+};
+
+#define object_label_offset object_label_u1.offset
+#define object_label_label object_label_u1.label
+
+#define object_label_reference object_label_u2.reference
+#define object_label_size object_label_u2.size
+#define object_label_string_offset object_label_u2.string_offset
+
+static struct object_label *first_object_label,**last_object_label_l;
+static struct object_label *code_csect_object_label,*data_csect_object_label;
+static int n_object_labels;
+#ifdef G_MACH_O
+static int n_exported_object_labels;
+static struct object_label *stub_csect_object_label;
+#endif
+
+static unsigned long string_table_offset;
+
+void define_data_label (LABEL *label)
+{
+ label->label_object_label=data_csect_object_label;
+ label->label_offset=CURRENT_DATA_OFFSET;
+
+ if (label->label_flags & EXPORT_LABEL){
+ struct object_label *new_object_label;
+ int string_length;
+
+ new_object_label=fast_memory_allocate_type (struct object_label);
+ *last_object_label_l=new_object_label;
+ last_object_label_l=&new_object_label->next;
+ new_object_label->next=NULL;
+
+ new_object_label->object_label_label=label;
+ new_object_label->object_label_number=n_object_labels;
+ ++n_object_labels;
+
+ string_length=strlen (label->label_name);
+#ifdef XCOFF
+ if (string_length<8)
+ new_object_label->object_label_string_offset=0;
+ else {
+#endif
+ new_object_label->object_label_string_offset=string_table_offset;
+ string_table_offset+=string_length+1;
+#ifdef XCOFF
+ }
+#endif
+ new_object_label->kind=EXPORTED_DATA_LABEL;
+ }
+}
+
+static void as_labels (struct block_label *labels)
+{
+ for (; labels!=NULL; labels=labels->block_label_next)
+#if 0
+ if (labels->block_label_label->label_number==0)
+#endif
+ {
+ LABEL *label;
+
+ label=labels->block_label_label;
+
+ label->label_object_label=code_csect_object_label;
+ label->label_offset=CURRENT_CODE_OFFSET;
+
+ if (label->label_flags & EXPORT_LABEL){
+ struct object_label *new_object_label;
+ int string_length;
+
+ code_csect_object_label->object_label_reference=-2;
+
+ new_object_label=fast_memory_allocate_type (struct object_label);
+ *last_object_label_l=new_object_label;
+ last_object_label_l=&new_object_label->next;
+ new_object_label->next=NULL;
+
+ new_object_label->object_label_label=label;
+ new_object_label->object_label_number=n_object_labels;
+ ++n_object_labels;
+
+ string_length=strlen (label->label_name);
+#ifdef XCOFF
+ if (string_length<8)
+ new_object_label->object_label_string_offset=0;
+ else {
+#endif
+ new_object_label->object_label_string_offset=string_table_offset;
+ string_table_offset+=string_length+1;
+#ifdef XCOFF
+ }
+#endif
+ new_object_label->kind=EXPORTED_CODE_LABEL;
+ }
+ }
+}
+
+extern void store_descriptor_string_in_data_section (char *string,int length,LABEL *string_label)
+{
+ define_data_label (string_label);
+ store_abc_string_in_data_section (string,length);
+}
+
+static void as_branch_label (struct label *label,int relocation_kind)
+{
+ struct relocation *new_relocation;
+
+ new_relocation=fast_memory_allocate_type (struct relocation);
+ ++n_code_relocations;
+
+ *last_code_relocation_l=new_relocation;
+ last_code_relocation_l=&new_relocation->next;
+ new_relocation->next=NULL;
+
+ new_relocation->relocation_label=label;
+ new_relocation->offset=CURRENT_CODE_OFFSET-4;
+ new_relocation->relocation_object_label=code_csect_object_label;
+ new_relocation->kind=relocation_kind;
+}
+
+enum { SIZE_LONG, SIZE_WORD, SIZE_BYTE };
+
+#define REGISTER_O0 (-13)
+#define REGISTER_O1 (-23)
+#define REGISTER_R0 (-24)
+#define RTOC (-22)
+#ifdef USE_DCBZ
+# define REGISTER_R9 (-15)
+#endif
+#define REGISTER_R3 (-21)
+
+static unsigned char real_reg_num [32] =
+{
+ 0,12,2,3,4,5,6,7,8,9,10,11,1,13,14,15,
+ 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+};
+
+#define reg_num(r) (real_reg_num[(r)+24])
+
+#define as_i_dai(i,rd,ra,si) store_instruction ((i<<26)|(reg_num(rd)<<21)|(reg_num(ra)<<16)|((UWORD)(si)))
+#define as_i_dad(i,rd,ra,d) store_instruction ((i<<26)|(reg_num(rd)<<21)|(reg_num(ra)<<16)|((UWORD)(d)))
+#define as_i_sab(rs,ra,rb,i2) store_instruction ((31<<26)|(reg_num(rs)<<21)|(reg_num(ra)<<16)|(reg_num(rb)<<11)|(i2<<1))
+#define as_i_dab(rd,ra,rb,i2) store_instruction ((31<<26)|(reg_num(rd)<<21)|(reg_num(ra)<<16)|(reg_num(rb)<<11)|(i2<<1))
+#define as_i_dabo_(rd,ra,rb,i2) store_instruction ((31<<26)|(reg_num(rd)<<21)|(reg_num(ra)<<16)|(reg_num(rb)<<11)|(i2<<1)|1025)
+#define as_i_sad(i,rs,ra,d) store_instruction ((i<<26)|(reg_num(rs)<<21)|(reg_num(ra)<<16)|((UWORD)(d)))
+#define as_i_sahbe(i,rs,ra,sh,mb,me) store_instruction ((i<<26)|(reg_num(rs)<<21)|(reg_num(ra)<<16)|(sh<<11)|(mb<<6)|(me<<1))
+#define as_i_dac(i,fd,fa,fb) store_instruction ((63<<26)|(fd<<21)|(fa<<16)|(fb<<11)|(i<<1))
+
+#define as_add(rd,ra,rb) as_i_dab (rd,ra,rb,266)
+#define as_addo_(rd,ra,rb) as_i_dabo_ (rd,ra,rb,266)
+#define as_addi(rd,ra,si) as_i_dai (14,rd,ra,si)
+#define as_addic_(rd,ra,si) as_i_dai (13,rd,ra,si)
+#define as_addis(rd,ra,si) as_i_dai (15,rd,ra,si)
+#define as_addze(rd,ra) store_instruction ((31<<26)|(reg_num(rd)<<21)|(reg_num(ra)<<16)|(202<<1))
+#define as_and(ra,rs,rb) as_i_sab (rs,ra,rb,28)
+#define as_andi_(ra,rs,si) as_i_dai (28,rs,ra,si)
+#define as_b() store_instruction (18<<26)
+#define as_bctr() store_instruction ((19<<26)|(20<<21)|(528<<1))
+#define as_bctrl() store_instruction ((19<<26)|(20<<21)|(528<<1)|1)
+#define as_bl() store_instruction ((18<<26)|1)
+#define as_blr() store_instruction ((19<<26)|(20<<21)|(16<<1))
+#define as_cmp(ra,rb) store_instruction ((31<<26)|(reg_num(ra)<<16)|(reg_num(rb)<<11)|(0<<1))
+#define as_cmpi(ra,si) store_instruction ((11<<26)|(reg_num(ra)<<16)|((UWORD)(si)))
+#define as_cmpl(ra,rb) store_instruction ((31<<26)|(reg_num(ra)<<16)|(reg_num(rb)<<11)|(32<<1))
+#define as_divw(rd,ra,rb) as_i_dab (rd,ra,rb,491)
+#define as_bc(i) store_instruction ((16<<26)|(i))
+#define as_bcl(i) store_instruction ((16<<26)|1|(i))
+#ifdef USE_DCBZ
+# define as_dcbz(ra,rb) store_instruction ((31<<26)|(reg_num(ra)<<16)|(reg_num(rb)<<11)|(1014<<1))
+#endif
+#define as_extb(ra,rb) store_instruction ((31<<26)|(reg_num(ra)<<21)|(reg_num(rb)<<16)|(954<<1))
+#define as_fadd(fd,fa,fc) as_i_dac (21,(fd),(fa),(fc))
+#define as_fcmpu(fa,fb) as_i_dac (0,0,(fa),(fb))
+#define as_fctiw(fd,fb) as_i_dac (14,(fd),0,(fb))
+#define as_fdiv(fd,fa,fc) as_i_dac (18,(fd),(fa),(fc))
+#define as_fmr(fd,fb) as_i_dac (72,(fd),0,(fb))
+#define as_fmadd(fd,fa,fb,fc) store_instruction ((63<<26)|((fd)<<21)|((fa)<<16)|((fc)<<11)|((fb)<<6)|(29<<1))
+#define as_fmsub(fd,fa,fb,fc) store_instruction ((63<<26)|((fd)<<21)|((fa)<<16)|((fc)<<11)|((fb)<<6)|(28<<1))
+#define as_fmul(fd,fa,fc) store_instruction ((63<<26)|((fd)<<21)|((fa)<<16)|((fc)<<6)|(25<<1))
+#define as_fnmsub(fd,fa,fb,fc) store_instruction ((63<<26)|((fd)<<21)|((fa)<<16)|((fc)<<11)|((fb)<<6)|(30<<1))
+#define as_fneg(fd,fb) as_i_dac (40,(fd),0,(fb))
+#define as_fsub(fd,fa,fc) as_i_dac (20,(fd),(fa),(fc))
+#define as_lbz(rd,d,ra) as_i_dad (34,rd,ra,d)
+#define as_lbzu(rd,d,ra) as_i_dad (35,rd,ra,d)
+#define as_lbzx(rd,ra,rb) as_i_dab (rd,ra,rb,87)
+#define as_lha(rd,d,ra) as_i_dad (42,rd,ra,d)
+#define as_lhau(rd,d,ra) as_i_dad (43,rd,ra,d)
+#define as_lhax(rd,ra,rb) as_i_dab (rd,ra,rb,343)
+#define as_lfd(fd,d,ra) store_instruction ((50<<26)|((fd)<<21)|(reg_num(ra)<<16)|(UWORD)d)
+#define as_lfdx(fd,ra,rb) store_instruction ((31<<26)|((fd)<<21)|(reg_num(ra)<<16)|(reg_num(rb)<<11)|(599<<1))
+#define as_lis(rd,si) as_addis (rd,REGISTER_R0,si)
+#define as_li(rd,si) as_addi (rd,REGISTER_R0,si)
+#define as_lwz(rd,d,ra) as_i_dad (32,rd,ra,d)
+#define as_lwzu(rd,d,ra) as_i_dad (33,rd,ra,d)
+#define as_lwzx(rd,ra,rb) as_i_dab (rd,ra,rb,23)
+#define as_mcrxr(rd) store_instruction ((31<<26)|(reg_num(rd)<<23)|(512<<1))
+#define as_mflr(rd) as_mfspr (8,rd)
+#define as_mfspr(spr,rd) store_instruction ((31<<26)|(reg_num(rd)<<21)|(spr<<16)|(339<<1));
+#define as_mr(rd,ra) as_or (rd,ra,ra)
+#define as_mtlr(rs) as_mtspr (8,rs)
+#define as_mtctr(rs) as_mtspr (9,rs)
+#define as_mtspr(spr,rs) store_instruction ((31<<26)|(reg_num(rs)<<21)|(spr<<16)|(467<<1));
+#define as_mulli(rd,ra,si) as_i_dai (7,rd,ra,si)
+#define as_mullw(rd,ra,rb) as_i_dab (rd,ra,rb,235)
+#define as_mullwo_(rd,ra,rb)as_i_dabo_ (rd,ra,rb,235)
+#define as_nop() store_instruction (24<<26)
+#define as_or(ra,rs,rb) as_i_sab (rs,ra,rb,444)
+#define as_ori(ra,rs,si) as_i_dai (24,rs,ra,si)
+#define as_oris(ra,rs,si) as_i_dai (25,rs,ra,si)
+#define as_rlwinm(ra,rs,sh,mb,me) as_i_sahbe (21,rs,ra,sh,mb,me)
+#define as_slw(ra,rs,rb) as_i_sab (rs,ra,rb,24)
+#define as_slwi(ra,rs,sh) as_rlwinm (ra,rs,sh,0,31-sh)
+#define as_sraw(ra,rs,rb) as_i_sab (rs,ra,rb,792)
+#define as_srawi(ra,rs,sh) store_instruction ((31<<26)|(reg_num (rs)<<21)|(reg_num(ra)<<16)|(sh<<11)|(824<<1))
+#define as_srw(ra,rs,rb) as_i_sab (rs,ra,rb,536)
+#define as_srwi(ra,rs,sh) as_rlwinm (ra,rs,32-sh,sh,31)
+#define as_stb(rs,d,ra) as_i_sad (38,rs,ra,d)
+#define as_stbu(rs,d,ra) as_i_sad (39,rs,ra,d)
+#define as_stbx(rs,ra,rb) as_i_sab (rs,ra,rb,215)
+#define as_stfd(fs,d,ra) store_instruction ((54<<26)|((fs)<<21)|(reg_num(ra)<<16)|(UWORD)d)
+#define as_stfdx(fs,ra,rb) store_instruction ((31<<26)|((fs)<<21)|(reg_num(ra)<<16)|(reg_num(rb)<<11)|(727<<1))
+#define as_sth(rs,d,ra) as_i_sad (44,rs,ra,d)
+#define as_sthu(rs,d,ra) as_i_sad (45,rs,ra,d)
+#define as_sthx(rs,ra,rb) as_i_sab (rs,ra,rb,407)
+#define as_stw(rs,d,ra) as_i_sad (36,rs,ra,d)
+#define as_stwu(rs,d,ra) as_i_sad (37,rs,ra,d)
+#define as_stwx(rs,ra,rb) as_i_sab (rs,ra,rb,151)
+#define as_sub(rx,ry,rz) as_subf (rx,rz,ry)
+#define as_subo_(rx,ry,rz) as_subfo_ (rx,rz,ry)
+#define as_subf(rd,ra,rb) as_i_dab (rd,ra,rb,40)
+#define as_subfo_(rd,ra,rb) as_i_dabo_ (rd,ra,rb,40)
+#define as_xor(ra,rs,rb) as_i_sab (rs,ra,rb,316)
+#define as_xori(ra,rs,si) as_i_dai (26,rs,ra,si)
+#define as_xoris(ra,rs,si) as_i_dai (27,rs,ra,si)
+
+#define w_i_dad(i,rd,ra,d) write_l ((i<<26)|(reg_num(rd)<<21)|(reg_num(ra)<<16)|((UWORD)(d)))
+#define w_i_dai(i,rd,ra,si) write_l ((i<<26)|(reg_num(rd)<<21)|(reg_num(ra)<<16)|((UWORD)(si)))
+
+#define w_addi(rd,ra,si) w_i_dai (14,rd,ra,si)
+#define w_addis(rd,ra,si) w_i_dai (15,rd,ra,si)
+#define w_bcl(i) write_l ((16<<26)|1|(i))
+#define w_bctr() write_l ((19<<26)|(20<<21)|(528<<1))
+#define w_lwz(rd,d,ra) w_i_dad (32,rd,ra,d)
+#define w_mflr(rd) w_mfspr (8,rd)
+#define w_mfspr(spr,rd) write_l ((31<<26)|(reg_num(rd)<<21)|(spr<<16)|(339<<1));
+#define w_mtlr(rs) w_mtspr (8,rs)
+#define w_mtctr(rs) w_mtspr (9,rs)
+#define w_mtspr(spr,rs) write_l ((31<<26)|(reg_num(rs)<<21)|(spr<<16)|(467<<1));
+
+static void as_load_label (struct label *label,int offset,int reg)
+{
+ struct toc_label *t_label;
+ struct relocation *new_relocation;
+
+#ifndef XCOFF
+# ifdef G_MACH_O
+ as_lis (reg,0);
+# else
+ as_lis (reg,(offset-(WORD)offset)>>16);
+# endif
+#else
+ t_label=new_toc_label (label,offset);
+
+ as_lwz (reg,t_label->toc_t_label_number<<2,RTOC);
+#endif
+ new_relocation=fast_memory_allocate_type (struct relocation);
+#ifndef G_MACH_O
+ ++n_code_relocations;
+#else
+ n_code_relocations+=2;
+#endif
+
+ *last_code_relocation_l=new_relocation;
+ last_code_relocation_l=&new_relocation->next;
+ new_relocation->next=NULL;
+
+ new_relocation->offset=CURRENT_CODE_OFFSET-4;
+ new_relocation->relocation_object_label=code_csect_object_label;
+
+#ifdef XCOFF
+ new_relocation->relocation_toc_label=t_label;
+# ifdef TRL_RELOCATIONS
+ if (label->label_flags & DATA_LABEL)
+ new_relocation->kind=TRL_RELOCATION;
+ else
+# endif
+ new_relocation->kind=TOC_RELOCATION;
+#else
+ new_relocation->relocation_label=label;
+ new_relocation->kind=HIGH_RELOCATION;
+ new_relocation->relocation_addend=offset;
+
+# ifdef G_MACH_O
+ as_addi (reg,reg,0);
+# else
+ as_addi (reg,reg,(WORD)offset);
+# endif
+
+ new_relocation=fast_memory_allocate_type (struct relocation);
+#ifndef G_MACH_O
+ ++n_code_relocations;
+#else
+ n_code_relocations+=2;
+#endif
+
+ *last_code_relocation_l=new_relocation;
+ last_code_relocation_l=&new_relocation->next;
+ new_relocation->next=NULL;
+
+ new_relocation->offset=CURRENT_CODE_OFFSET-4;
+ new_relocation->relocation_object_label=code_csect_object_label;
+ new_relocation->relocation_label=label;
+ new_relocation->kind=LOW_RELOCATION;
+ new_relocation->relocation_addend=offset;
+#endif
+}
+
+#ifndef XCOFF
+
+# define as_load_label1(label,offset,reg,relocation_kind) as_load_label(label,offset,reg)
+
+static void store_label_in_code_section (struct label *label,int offset)
+{
+ struct toc_label *t_label;
+ struct relocation *new_relocation;
+
+ store_instruction (0);
+
+ new_relocation=fast_memory_allocate_type (struct relocation);
+ ++n_code_relocations;
+
+ *last_code_relocation_l=new_relocation;
+ last_code_relocation_l=&new_relocation->next;
+ new_relocation->next=NULL;
+
+ new_relocation->offset=CURRENT_CODE_OFFSET-4;
+ new_relocation->relocation_object_label=code_csect_object_label;
+
+ new_relocation->relocation_label=label;
+ new_relocation->kind=LONG_WORD_RELOCATION;
+ new_relocation->relocation_addend=offset;
+}
+
+#else
+static void as_load_label1 (struct label *label,int offset,int reg,int relocation_kind)
+{
+ struct toc_label *t_label;
+ struct relocation *new_relocation;
+
+ t_label=new_toc_label (label,offset);
+
+ as_lwz (reg,t_label->toc_t_label_number<<2,RTOC);
+
+ new_relocation=fast_memory_allocate_type (struct relocation);
+ ++n_code_relocations;
+
+ *last_code_relocation_l=new_relocation;
+ last_code_relocation_l=&new_relocation->next;
+ new_relocation->next=NULL;
+
+ new_relocation->offset=CURRENT_CODE_OFFSET-4;
+ new_relocation->relocation_object_label=code_csect_object_label;
+ new_relocation->relocation_toc_label=t_label;
+ new_relocation->kind=relocation_kind;
+}
+#endif
+
+static void as_load_descriptor (struct parameter *parameter,int reg)
+{
+ as_load_label1 (parameter->parameter_data.l,2+(parameter->parameter_offset<<3),reg,TRL_RELOCATION);
+}
+
+static void as_load_label_parameter (struct parameter *parameter,int reg)
+{
+ as_load_label (parameter->parameter_data.l,parameter->parameter_offset,reg);
+}
+
+static int as_register_parameter (struct parameter parameter,int size_flag)
+{
+ switch (parameter.parameter_type){
+ case P_DESCRIPTOR_NUMBER:
+ as_load_descriptor (&parameter,REGISTER_O0);
+ return REGISTER_O0;
+ case P_IMMEDIATE:
+ {
+ int i;
+
+ i=parameter.parameter_data.i;
+
+ if (i!=(WORD)i){
+ as_lis (REGISTER_O0,(i-(WORD)i)>>16);
+
+ i=(WORD)i;
+
+ as_addi (REGISTER_O0,REGISTER_O0,i);
+ } else
+ as_li (REGISTER_O0,i);
+
+ return REGISTER_O0;
+ }
+ case P_REGISTER:
+ return parameter.parameter_data.reg.r;
+ case P_INDIRECT:
+ if (size_flag==SIZE_LONG)
+ as_lwz (REGISTER_O0,parameter.parameter_offset,parameter.parameter_data.reg.r);
+ else if (size_flag==SIZE_WORD)
+ as_lha (REGISTER_O0,parameter.parameter_offset,parameter.parameter_data.reg.r);
+ else
+ as_lbz (REGISTER_O0,parameter.parameter_offset,parameter.parameter_data.reg.r);
+
+ return REGISTER_O0;
+ case P_INDIRECT_WITH_UPDATE:
+ if (size_flag==SIZE_LONG)
+ as_lwzu (REGISTER_O0,parameter.parameter_offset,parameter.parameter_data.reg.r);
+ else if (size_flag==SIZE_WORD)
+ as_lhau (REGISTER_O0,parameter.parameter_offset,parameter.parameter_data.reg.r);
+ else
+ as_lbzu (REGISTER_O0,parameter.parameter_offset,parameter.parameter_data.reg.r);
+
+ return REGISTER_O0;
+ case P_INDEXED:
+ if (size_flag==SIZE_LONG)
+ as_lwzx (REGISTER_O0,parameter.parameter_data.ir->a_reg.r,parameter.parameter_data.ir->d_reg.r);
+ else if (size_flag==SIZE_WORD)
+ as_lhax (REGISTER_O0,parameter.parameter_data.ir->a_reg.r,parameter.parameter_data.ir->d_reg.r);
+ else
+ as_lbzx (REGISTER_O0,parameter.parameter_data.ir->a_reg.r,parameter.parameter_data.ir->d_reg.r);
+
+ return REGISTER_O0;
+ default:
+ internal_error_in_function ("as_register_parameter");
+ return REGISTER_O0;
+ }
+}
+
+static void as_move_instruction (struct instruction *instruction,int size_flag)
+{
+ switch (instruction->instruction_parameters[1].parameter_type){
+ case P_REGISTER:
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_DESCRIPTOR_NUMBER:
+ as_load_descriptor (
+ &instruction->instruction_parameters[0],
+ instruction->instruction_parameters[1].parameter_data.reg.r
+ );
+ return;
+ case P_IMMEDIATE:
+ {
+ int i,r;
+
+ i=instruction->instruction_parameters[0].parameter_data.i;
+ r=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ if (i!=(WORD)i){
+ as_lis (r,(i-(WORD)i)>>16);
+
+ i=(WORD)i;
+
+ as_addi (r,r,i);
+ } else
+ as_li (r,i);
+ return;
+ }
+ case P_REGISTER:
+ as_mr ( instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ return;
+ case P_INDIRECT:
+ if (size_flag==SIZE_LONG)
+ as_lwz (
+ instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ else if (size_flag==SIZE_WORD)
+ as_lha (
+ instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ else
+ as_lbz (
+ instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ return;
+ case P_INDIRECT_WITH_UPDATE:
+ if (size_flag==SIZE_LONG)
+ as_lwzu (
+ instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ else if (size_flag==SIZE_WORD)
+ as_lhau (
+ instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ else
+ as_lbzu (
+ instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ return;
+ case P_INDEXED:
+ if (size_flag==SIZE_LONG)
+ as_lwzx (
+ instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[0].parameter_data.ir->a_reg.r,
+ instruction->instruction_parameters[0].parameter_data.ir->d_reg.r);
+ else if (size_flag==SIZE_WORD)
+ as_lhax (
+ instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[0].parameter_data.ir->a_reg.r,
+ instruction->instruction_parameters[0].parameter_data.ir->d_reg.r);
+ else
+ as_lbzx (
+ instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[0].parameter_data.ir->a_reg.r,
+ instruction->instruction_parameters[0].parameter_data.ir->d_reg.r);
+ return;
+ default:
+ internal_error_in_function ("as_move_instruction");
+ return;
+ }
+ case P_INDIRECT:
+ {
+ int reg;
+
+ reg=as_register_parameter (instruction->instruction_parameters[0],size_flag);
+
+ if (size_flag==SIZE_LONG)
+ as_stw (reg,
+ instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ else if (size_flag==SIZE_WORD)
+ as_sth (reg,
+ instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ else
+ as_stb (reg,
+ instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ }
+ case P_INDIRECT_WITH_UPDATE:
+ {
+ int reg;
+
+ reg=as_register_parameter (instruction->instruction_parameters[0],size_flag);
+
+ if (size_flag==SIZE_LONG)
+ as_stwu (reg,
+ instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ else if (size_flag==SIZE_WORD)
+ as_sthu (reg,
+ instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ else
+ as_stbu (reg,
+ instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ }
+ case P_INDEXED:
+ {
+ int reg;
+
+ reg=as_register_parameter (instruction->instruction_parameters[0],size_flag);
+
+ if (size_flag==SIZE_LONG)
+ as_stwx (reg,
+ instruction->instruction_parameters[1].parameter_data.ir->a_reg.r,
+ instruction->instruction_parameters[1].parameter_data.ir->d_reg.r);
+ else if (size_flag==SIZE_WORD)
+ as_sthx (reg,
+ instruction->instruction_parameters[1].parameter_data.ir->a_reg.r,
+ instruction->instruction_parameters[1].parameter_data.ir->d_reg.r);
+ else
+ as_stbx (reg,
+ instruction->instruction_parameters[1].parameter_data.ir->a_reg.r,
+ instruction->instruction_parameters[1].parameter_data.ir->d_reg.r);
+ return;
+ }
+ case P_INDIRECT_HP:
+ {
+ int reg1,reg2;
+ LONG offset;
+
+ reg1=as_register_parameter (instruction->instruction_parameters[0],size_flag);
+ offset=instruction->instruction_parameters[1].parameter_data.i;
+ reg2=HEAP_POINTER;
+
+ if (offset!=(WORD)offset){
+ as_addis (REGISTER_O0,reg2,(offset-(WORD)offset)>>16);
+ reg2=REGISTER_O0;
+ offset=(WORD)offset;
+ }
+
+ if (size_flag==SIZE_LONG)
+ as_stw (reg1,offset,reg2);
+ else if (size_flag==SIZE_WORD)
+ as_sth (reg1,offset,reg2);
+ else
+ as_stb (reg1,offset,reg2);
+ return;
+ }
+ default:
+ internal_error_in_function ("as_move_instruction");
+ }
+}
+
+static void as_lea_instruction (struct instruction *instruction)
+{
+ if (instruction->instruction_parameters[1].parameter_type==P_REGISTER)
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_LABEL:
+ as_load_label_parameter (&instruction->instruction_parameters[0],
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_INDIRECT:
+ as_addi (
+ instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[0].parameter_data.reg.r,
+ instruction->instruction_parameters[0].parameter_offset);
+ return;
+ case P_INDEXED:
+ as_add (
+ instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[0].parameter_data.ir->a_reg.r,
+ instruction->instruction_parameters[0].parameter_data.ir->d_reg.r);
+ return;
+ }
+
+ internal_error_in_function ("as_lea_instruction");
+}
+
+static void as_addi_instruction (struct instruction *instruction)
+{
+ as_addi (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[0].parameter_data.reg.r,
+ instruction->instruction_parameters[2].parameter_data.i);
+}
+
+static void as_add_instruction (struct instruction *instruction)
+{
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_REGISTER:
+ as_add (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ return;
+ case P_IMMEDIATE:
+ {
+ int i,r;
+
+ i=instruction->instruction_parameters[0].parameter_data.i;
+ r=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ if (i!=(WORD)i){
+ as_addis (r,r,(i-(WORD)i)>>16);
+
+ i=(WORD)i;
+ }
+
+ as_addi (r,r,i);
+ return;
+ }
+ default:
+ {
+ int reg;
+
+ reg=as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ as_add (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r,reg);
+ }
+ }
+}
+
+static void as_extb_instruction (struct instruction *instruction)
+{
+ int reg;
+
+ reg=instruction->instruction_parameters[0].parameter_data.reg.r;
+
+ as_extb (reg,reg);
+}
+
+static void as_addo_instruction (struct instruction *instruction)
+{
+ int reg;
+
+ reg=as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ as_addo_ (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r,reg);
+}
+
+static void as_sub_instruction (struct instruction *instruction)
+{
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_REGISTER:
+ as_sub (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ return;
+ case P_IMMEDIATE:
+ {
+ int i,r;
+
+ i= -instruction->instruction_parameters[0].parameter_data.i;
+ r=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ if (i!=(WORD)i){
+ as_addis (r,r,(i-(WORD)i)>>16);
+
+ i=(WORD)i;
+ }
+
+ as_addi (r,r,i);
+ return;
+ }
+ default:
+ {
+ int reg;
+
+ reg=as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ as_sub (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r,reg);
+ }
+ }
+}
+
+static void as_subo_instruction (struct instruction *instruction)
+{
+ int reg;
+
+ reg=as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ as_subo_ (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r,reg);
+}
+
+static void as_cmp_instruction (struct instruction *instruction,int size_flag)
+{
+ struct parameter parameter_0,parameter_1;
+
+ parameter_0=instruction->instruction_parameters[0];
+ parameter_1=instruction->instruction_parameters[1];
+
+ if (parameter_1.parameter_type==P_INDIRECT){
+ if (size_flag==SIZE_LONG)
+ as_lwz (REGISTER_O1,parameter_1.parameter_offset,parameter_1.parameter_data.reg.r);
+ else
+ as_lha (REGISTER_O1,parameter_1.parameter_offset,parameter_1.parameter_data.reg.r);
+
+ parameter_1.parameter_type=P_REGISTER;
+ parameter_1.parameter_data.reg.r=REGISTER_O1;
+ } else if (parameter_1.parameter_type==P_INDEXED){
+ if (size_flag==SIZE_LONG)
+ as_lwzx (REGISTER_O1,parameter_1.parameter_data.ir->a_reg.r,parameter_1.parameter_data.ir->d_reg.r);
+ else
+ as_lhax (REGISTER_O1,parameter_1.parameter_data.ir->a_reg.r,parameter_1.parameter_data.ir->d_reg.r);
+
+ parameter_1.parameter_type=P_REGISTER;
+ parameter_1.parameter_data.reg.r=REGISTER_O1;
+ }
+
+ switch (parameter_0.parameter_type){
+ case P_DESCRIPTOR_NUMBER:
+ as_load_descriptor (&parameter_0,REGISTER_O0);
+
+ parameter_0.parameter_type=P_REGISTER;
+ parameter_0.parameter_data.reg.r=REGISTER_O0;
+ break;
+ case P_REGISTER:
+ break;
+ case P_IMMEDIATE:
+ {
+ int i;
+
+ i=parameter_0.parameter_data.i;
+
+ if (i!=(WORD)i){
+ as_lis (REGISTER_O0,(i-(WORD)i)>>16);
+
+ i=(WORD)i;
+
+ as_addi (REGISTER_O0,REGISTER_O0,i);
+
+ parameter_0.parameter_type=P_REGISTER;
+ parameter_0.parameter_data.reg.r=REGISTER_O0;
+ }
+ break;
+ }
+ case P_INDIRECT:
+ switch (size_flag){
+ case SIZE_WORD:
+ as_lha (REGISTER_O0,parameter_0.parameter_offset,parameter_0.parameter_data.reg.r);
+ break;
+ case SIZE_LONG:
+ as_lwz (REGISTER_O0,parameter_0.parameter_offset,parameter_0.parameter_data.reg.r);
+ break;
+ default:
+ internal_error_in_function ("as_cmp_instruction");
+ }
+
+ parameter_0.parameter_type=P_REGISTER;
+ parameter_0.parameter_data.reg.r=REGISTER_O0;
+ break;
+ case P_INDEXED:
+ switch (size_flag){
+ case SIZE_WORD:
+ as_lhax (REGISTER_O0,parameter_0.parameter_data.ir->a_reg.r,parameter_0.parameter_data.ir->d_reg.r);
+ break;
+ case SIZE_LONG:
+ as_lwzx (REGISTER_O0,parameter_0.parameter_data.ir->a_reg.r,parameter_0.parameter_data.ir->d_reg.r);
+ break;
+ default:
+ internal_error_in_function ("as_cmp_instruction");
+ }
+
+ parameter_0.parameter_type=P_REGISTER;
+ parameter_0.parameter_data.reg.r=REGISTER_O0;
+ break;
+ }
+
+ if (parameter_0.parameter_type==P_IMMEDIATE){
+ as_cmpi (parameter_1.parameter_data.reg.r,parameter_0.parameter_data.i);
+ } else
+ as_cmp (parameter_1.parameter_data.reg.r,parameter_0.parameter_data.reg.r);
+}
+
+static void as_cmplw_instruction (struct instruction *instruction)
+{
+ if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT &&
+ instruction->instruction_parameters[1].parameter_type==P_REGISTER)
+ {
+ as_lwz (REGISTER_O0,instruction->instruction_parameters[0].parameter_offset,instruction->instruction_parameters[0].parameter_data.reg.r);
+ as_cmpl (instruction->instruction_parameters[1].parameter_data.reg.r,REGISTER_O0);
+ } else
+ internal_error_in_function ("as_cmplw_instruction");
+}
+
+static void as_slwi_instruction (struct instruction *instruction)
+{
+ as_slwi (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[0].parameter_data.reg.r,
+ instruction->instruction_parameters[2].parameter_data.i);
+}
+
+static void as_slw_instruction (struct instruction *instruction)
+{
+ if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){
+ as_slwi (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[0].parameter_data.i);
+ } else {
+ int reg;
+
+ reg=as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ as_slw (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r,reg);
+ }
+}
+
+static void as_srw_instruction (struct instruction *instruction)
+{
+ if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){
+ as_srwi (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[0].parameter_data.i);
+ } else {
+ int reg;
+
+ reg=as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ as_srw (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r,reg);
+ }
+}
+
+static void as_sraw_instruction (struct instruction *instruction)
+{
+ if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){
+ as_srawi (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[0].parameter_data.i);
+ } else {
+ int reg;
+
+ reg=as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ as_sraw (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r,reg);
+ }
+}
+
+static void as_mul_instruction (struct instruction *instruction)
+{
+ int r,reg;
+
+ r=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_IMMEDIATE:
+ {
+ int i;
+
+ i=instruction->instruction_parameters[0].parameter_data.i;
+
+ if (i!=(WORD)i){
+ as_lis (REGISTER_O0,(i-(WORD)i)>>16);
+
+ i=(WORD)i;
+
+ as_addi (REGISTER_O0,REGISTER_O0,i);
+ } else {
+ as_mulli (r,r,i);
+ return;
+ }
+
+ reg=REGISTER_O0;
+ break;
+ }
+ default:
+ reg=as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+ }
+
+ as_mullw (r,r,reg);
+}
+
+static void as_mulo_instruction (struct instruction *instruction)
+{
+ int r,reg;
+
+ reg=as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ r=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ as_mullwo_ (r,r,reg);
+}
+
+static void as_div_instruction (struct instruction *instruction)
+{
+ int reg;
+
+ if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){
+ int i,sd_reg;
+
+ i=instruction->instruction_parameters[0].parameter_data.i;
+ if ((i & (i-1))==0 && i>0){
+ int log2i;
+
+ if (i==1)
+ return;
+
+ log2i=0;
+ while (i>1){
+ i=i>>1;
+ ++log2i;
+ }
+
+ sd_reg=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ as_srawi (sd_reg,sd_reg,log2i);
+ as_addze (sd_reg,sd_reg);
+
+ return;
+ }
+ }
+
+ reg=as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ as_divw (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r,reg);
+}
+
+static void as_rem_instruction (struct instruction *instruction)
+{
+ int reg;
+
+ if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){
+ int i,sd_reg;
+
+ i=instruction->instruction_parameters[0].parameter_data.i;
+ if ((i & (i-1))==0 && i>1){
+ int log2i;
+
+ log2i=0;
+ while (i>1){
+ i=i>>1;
+ ++log2i;
+ }
+
+ sd_reg=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ as_srawi (REGISTER_O1,sd_reg,31);
+
+ if (log2i==1){
+ as_andi_ (sd_reg,sd_reg,1);
+ as_xor (sd_reg,sd_reg,REGISTER_O1);
+ } else {
+ as_rlwinm (REGISTER_O1,REGISTER_O1,0,32-log2i,31);
+ as_add (sd_reg,sd_reg,REGISTER_O1);
+ as_rlwinm (sd_reg,sd_reg,0,32-log2i,31);
+ }
+
+ as_sub (sd_reg,sd_reg,REGISTER_O1);
+
+ return;
+ }
+ }
+
+ reg=as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ as_divw (REGISTER_O1,instruction->instruction_parameters[1].parameter_data.reg.r,reg);
+ as_mullw (REGISTER_O1,REGISTER_O1,reg);
+ as_sub (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r,REGISTER_O1);
+}
+
+static void as_and_instruction (struct instruction *instruction)
+{
+ int reg;
+
+ if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){
+ int i;
+
+ i=instruction->instruction_parameters[0].parameter_data.i;
+
+ if (i==(UWORD)i){
+ as_andi_ (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r,i);
+ return;
+ } else {
+ as_lis (REGISTER_O0,(i-(WORD)i)>>16);
+
+ i=(WORD)i;
+
+ as_addi (REGISTER_O0,REGISTER_O0,i);
+
+ reg=REGISTER_O0;
+ }
+ } else
+ reg=as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ as_and (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r,reg);
+}
+
+static void as_or_instruction (struct instruction *instruction)
+{
+ if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){
+ long i;
+
+ i=instruction->instruction_parameters[0].parameter_data.i;
+
+ if ((unsigned short) i != i){
+ int h;
+
+ h=(unsigned)i >> (unsigned)16;
+
+ as_oris (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r,h);
+
+ i=(unsigned short)i;
+ }
+
+ as_ori (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r,i);
+ } else {
+ int reg;
+
+ reg=as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ as_or (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r,reg);
+ }
+}
+
+static void as_xor_instruction (struct instruction *instruction)
+{
+ if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){
+ long i;
+
+ i=instruction->instruction_parameters[0].parameter_data.i;
+
+ if ((unsigned short) i != i){
+ int h;
+
+ h=(unsigned)i >> (unsigned)16;
+
+ as_xoris (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r,h);
+
+ i=(unsigned short)i;
+ }
+
+ as_xori (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r,i);
+ } else {
+ int reg;
+
+ reg=as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ as_xor (instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r,reg);
+ }
+}
+
+static void as_tst_instruction (struct instruction *instruction)
+{
+ int reg;
+
+ reg=as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ as_cmpi (reg,0);
+}
+
+static void as_jmp_instruction (struct instruction *instruction)
+{
+ struct parameter *parameter0;
+
+ parameter0=&instruction->instruction_parameters[0];
+
+ switch (parameter0->parameter_type){
+ case P_LABEL:
+ as_b();
+ as_branch_label (parameter0->parameter_data.l,BRANCH_RELOCATION);
+ return;
+ case P_INDIRECT:
+ {
+ int offset,reg;
+
+ offset=parameter0->parameter_offset;
+ reg=parameter0->parameter_data.reg.r;
+
+ if (offset!=0){
+ as_addi (REGISTER_O0,reg,offset);
+
+ as_mtctr (REGISTER_O0);
+ } else
+ as_mtctr (reg);
+
+ as_bctr();
+ return;
+ }
+ default:
+ internal_error_in_function ("as_jmp_instruction");
+ }
+}
+
+static void as_jmpp_instruction (struct instruction *instruction)
+{
+ struct parameter *parameter0;
+ int offset;
+
+ parameter0=&instruction->instruction_parameters[0];
+ offset=parameter0->parameter_offset;
+
+ switch (parameter0->parameter_type){
+ case P_LABEL:
+ if (offset==0){
+ as_mflr (REGISTER_R0);
+ as_bl();
+ as_branch_label (profile_t_label,BRANCH_RELOCATION);
+ }
+
+ store_instruction ((18<<26) + offset);
+ as_branch_label (instruction->instruction_parameters[0].parameter_data.l,BRANCH_RELOCATION);
+ return;
+ case P_INDIRECT:
+ {
+ int reg;
+
+ reg=parameter0->parameter_data.reg.r;
+
+ if (offset!=0){
+ as_addi (REGISTER_O0,reg,offset);
+
+ as_mtctr (REGISTER_O0);
+ } else
+ as_mtctr (reg);
+
+ as_b();
+ as_branch_label (profile_ti_label,BRANCH_RELOCATION);
+ return;
+ }
+ default:
+ internal_error_in_function ("as_jmpp_instruction");
+ }
+}
+
+static void write_c (int c)
+{
+ fputc (c,output_file);
+}
+
+static void write_w (int c)
+{
+ fputc (c>>8,output_file);
+ fputc (c,output_file);
+}
+
+static void write_l (int c)
+{
+ fputc (c>>24,output_file);
+ fputc (c>>16,output_file);
+ fputc (c>>8,output_file);
+ fputc (c,output_file);
+}
+
+#ifdef G_MACH_O
+struct stub {
+ LABEL *stub_label;
+ struct object_label *stub_object_label;
+ struct stub *stub_next;
+};
+
+static struct stub *first_stub,**next_stub_l;
+static int n_stubs;
+
+static void compute_offsets_of_stub_labels (void)
+{
+ struct stub *stub;
+ unsigned int stub_offset1;
+
+ stub_offset1=code_buffer_offset+data_buffer_offset;
+
+ for_l (stub,first_stub,stub_next){
+ LABEL *label;
+
+ label=stub->stub_label;
+ label->label_offset=stub_offset1;
+ label->label_flags &= ~STUB_GENERATED;
+
+ stub_offset1+=36;
+ }
+}
+
+static void write_stubs (void)
+{
+ struct stub *stub;
+ unsigned int stub_offset1,stub_offset2;
+
+ stub_offset1=code_buffer_offset+data_buffer_offset;
+ stub_offset2=stub_offset1+n_stubs*36;
+
+ for_l (stub,first_stub,stub_next){
+ unsigned int offset_diff;
+
+ offset_diff=stub_offset2-(stub_offset1+8);
+ w_mflr (REGISTER_R0);
+ w_bcl ((20<<21)|(31<<16)|4);
+ w_mflr (REGISTER_O0);
+ w_addis (REGISTER_O0,REGISTER_O0,(offset_diff-(WORD)offset_diff)>>16);
+ w_mtlr (REGISTER_R0);
+ w_lwz (REGISTER_O1,offset_diff & 0xffff,REGISTER_O0);
+ w_mtctr (REGISTER_O1);
+ w_addi (REGISTER_O0,REGISTER_O0,offset_diff & 0xffff);
+ w_bctr();
+
+ stub_offset1+=36;
+ stub_offset2+=4;
+ }
+
+ for_l (stub,first_stub,stub_next)
+ write_l (0);
+}
+
+extern LABEL *dyld_stub_binding_helper_p_label;
+
+static void write_stub_relocations_and_indirect_symbols (void)
+{
+ struct stub *stub;
+ unsigned int stub_offset1,stub_offset2,picsymbol_stub_section_offset;
+
+ picsymbol_stub_section_offset=code_buffer_offset+data_buffer_offset;
+
+ stub_offset1=0;
+ stub_offset2=picsymbol_stub_section_offset+n_stubs*36;
+
+ for_l (stub,first_stub,stub_next){
+ unsigned int offset_diff;
+
+ offset_diff=stub_offset2-(picsymbol_stub_section_offset+stub_offset1+8);
+
+ write_l ((1<<31) | (2<<28) | (PPC_RELOC_HA16_SECTDIFF<<24) | (stub_offset1+12));
+ write_l (stub_offset2);
+ write_l ((1<<31) | (2<<28) | (PPC_RELOC_PAIR<<24) | (offset_diff & 0xffff));
+ write_l (picsymbol_stub_section_offset+stub_offset1+8);
+
+ write_l ((1<<31) | (2<<28) | (PPC_RELOC_LO16_SECTDIFF<<24) | (stub_offset1+20));
+ write_l (stub_offset2);
+ write_l ((1<<31) | (2<<28) | (PPC_RELOC_PAIR<<24) | (offset_diff>>16));
+ write_l (picsymbol_stub_section_offset+stub_offset1+8);
+
+ write_l ((1<<31) | (2<<28) | (PPC_RELOC_LO16_SECTDIFF<<24) | (stub_offset1+28));
+ write_l (stub_offset2);
+ write_l ((1<<31) | (2<<28) | (PPC_RELOC_PAIR<<24) | (offset_diff>>16));
+ write_l (picsymbol_stub_section_offset+stub_offset1+8);
+
+ stub_offset1+=36;
+ stub_offset2+=4;
+ }
+
+ stub_offset2=0;
+ for_l (stub,first_stub,stub_next){
+ write_l (stub_offset2);
+ write_l (PPC_RELOC_VANILLA | (2<<5) | (1<<4) | (dyld_stub_binding_helper_p_label->label_object_label->object_label_number<<8));
+ stub_offset2+=4;
+ }
+
+ for_l (stub,first_stub,stub_next){
+ struct object_label *object_label;
+
+ object_label=stub->stub_object_label;
+ if (object_label->kind!=IMPORTED_CODE_LABEL)
+ internal_error_in_function ("write_stub_relocations_and_indirect_symbols");
+
+ write_l (object_label->object_label_number);
+ }
+
+ for_l (stub,first_stub,stub_next)
+ write_l (stub->stub_object_label->object_label_number);
+}
+#endif
+
+static void as_jsr_instruction (struct instruction *instruction)
+{
+ struct parameter *parameter0;
+
+ parameter0=&instruction->instruction_parameters[0];
+
+ if (instruction->instruction_parameters[1].parameter_type==P_REGISTER){
+ int frame_size;
+
+ frame_size=instruction->instruction_parameters[1].parameter_data.i;
+
+ if (parameter0->parameter_type==P_REGISTER)
+ as_mtctr (parameter0->parameter_data.reg.r);
+
+ if (!(instruction->instruction_arity & NO_MFLR))
+ as_mflr (REGISTER_R0);
+
+#ifdef ALIGN_C_CALLS
+# if 0
+ as_mr (REGISTER_O0,B_STACK_POINTER);
+ as_ori (B_STACK_POINTER,B_STACK_POINTER,28);
+# endif
+ as_stw (REGISTER_R0,-28-4,B_STACK_POINTER);
+ as_stwu (REGISTER_O0,-(frame_size+28),B_STACK_POINTER);
+#else
+ as_stw (REGISTER_R0,-4,B_STACK_POINTER);
+ as_stwu (B_STACK_POINTER,-frame_size,B_STACK_POINTER);
+#endif
+ if (parameter0->parameter_type==P_REGISTER){
+ as_bctrl();
+ } else {
+ struct label *label;
+
+ as_bl();
+
+ label=parameter0->parameter_data.l;
+#ifdef G_MACH_O
+ if (label->label_name[0]=='_'){
+ if (!(label->label_flags & STUB_GENERATED)){
+ struct stub *new_stub;
+
+ label->label_flags |= STUB_GENERATED;
+ label->label_offset=n_stubs*36;
+
+ if (stub_csect_object_label==NULL){
+ struct object_label *new_object_label;
+
+ new_object_label=fast_memory_allocate_type (struct object_label);
+ stub_csect_object_label=new_object_label;
+
+ new_object_label->object_label_reference=-1;
+ new_object_label->object_label_offset=0;
+ new_object_label->object_label_number=-1;
+ new_object_label->kind=STUB_CONTROL_SECTION;
+ }
+
+ new_stub=allocate_memory_from_heap (sizeof (struct stub));
+
+ new_stub->stub_label=label;
+ new_stub->stub_object_label=label->label_object_label;
+ label->label_object_label=stub_csect_object_label;
+
+ *next_stub_l=new_stub;
+ next_stub_l=&new_stub->stub_next;
+ new_stub->stub_next=NULL;
+ ++n_stubs;
+ }
+ }
+#endif
+ as_branch_label (label,BRANCH_RELOCATION);
+ }
+
+ as_nop();
+
+#ifdef ALIGN_C_CALLS
+ as_lwz (REGISTER_R0,frame_size-4,B_STACK_POINTER);
+ as_lwz (B_STACK_POINTER,0,B_STACK_POINTER);
+#else
+ as_lwz (REGISTER_R0,frame_size-4,B_STACK_POINTER);
+ as_addi (B_STACK_POINTER,B_STACK_POINTER,frame_size);
+#endif
+ if (!(instruction->instruction_arity & NO_MTLR))
+ as_mtlr (REGISTER_R0);
+
+ return;
+ }
+
+ if (parameter0->parameter_type==P_INDIRECT){
+ int offset,reg;
+
+ offset=parameter0->parameter_offset;
+ reg=parameter0->parameter_data.reg.r;
+
+ if (offset!=0){
+ as_addi (REGISTER_O0,reg,offset);
+ as_mtctr (REGISTER_O0);
+ } else
+ as_mtctr (reg);
+ }
+
+ if (!(instruction->instruction_arity & NO_MFLR))
+ as_mflr (REGISTER_R0);
+
+ if (instruction->instruction_parameters[1].parameter_type==P_INDIRECT_WITH_UPDATE)
+ as_stwu (REGISTER_R0,instruction->instruction_parameters[1].parameter_data.i,B_STACK_POINTER);
+ else
+ as_stw (REGISTER_R0,instruction->instruction_parameters[1].parameter_data.i,B_STACK_POINTER);
+
+ switch (parameter0->parameter_type){
+ case P_LABEL:
+ as_bl();
+ as_branch_label (parameter0->parameter_data.l,BRANCH_RELOCATION);
+ break;
+ case P_INDIRECT:
+ as_bctrl();
+ break;
+ default:
+ internal_error_in_function ("as_jsr_instruction");
+ }
+
+ if (!(instruction->instruction_arity & NO_MTLR))
+ as_mtlr (REGISTER_R0);
+}
+
+static void as_new_code_module (void)
+{
+ struct object_label *new_object_label;
+ unsigned long current_code_offset;
+ int code_section_label_number;
+
+#ifndef XCOFF
+ if (code_csect_object_label!=NULL)
+ return;
+#endif
+
+ new_object_label=fast_memory_allocate_type (struct object_label);
+ code_csect_object_label=new_object_label;
+
+ code_section_label_number=n_object_labels;
+ ++n_object_labels;
+
+ current_code_offset=CURRENT_CODE_OFFSET;
+
+ *last_object_label_l=new_object_label;
+ last_object_label_l=&new_object_label->next;
+ new_object_label->next=NULL;
+
+ new_object_label->object_label_reference=-1;
+ new_object_label->object_label_offset=current_code_offset;
+ new_object_label->object_label_number=code_section_label_number;
+ new_object_label->kind=CODE_CONTROL_SECTION;
+}
+
+void as_new_data_module (void)
+{
+ struct object_label *new_object_label;
+ unsigned long current_data_offset;
+ int data_section_label_number;
+
+#ifndef XCOFF
+ if (data_csect_object_label!=NULL)
+ return;
+#endif
+
+ new_object_label=fast_memory_allocate_type (struct object_label);
+ data_csect_object_label=new_object_label;
+
+ data_section_label_number=n_object_labels;
+ ++n_object_labels;
+
+ current_data_offset=CURRENT_DATA_OFFSET;
+
+ *last_object_label_l=new_object_label;
+ last_object_label_l=&new_object_label->next;
+ new_object_label->next=NULL;
+
+ new_object_label->object_label_reference=-1;
+ new_object_label->object_label_offset=current_data_offset;
+ new_object_label->object_label_number=data_section_label_number;
+ new_object_label->kind=DATA_CONTROL_SECTION;
+}
+
+struct call_and_jump {
+ struct call_and_jump * cj_next;
+ struct label * cj_call_label;
+ struct label cj_label;
+ struct label cj_jump_label;
+};
+
+static struct call_and_jump *first_call_and_jump,*last_call_and_jump;
+
+static void as_call_and_jump (struct call_and_jump *call_and_jump)
+{
+ call_and_jump->cj_label.label_object_label=code_csect_object_label;
+ call_and_jump->cj_label.label_offset=CURRENT_CODE_OFFSET;
+
+ if (call_and_jump->cj_jump_label.label_flags & FAR_CONDITIONAL_JUMP_LABEL){
+ as_b();
+ as_branch_label (call_and_jump->cj_call_label,BRANCH_RELOCATION);
+ } else {
+ as_mflr (REGISTER_R0);
+
+ as_bl();
+ as_branch_label (call_and_jump->cj_call_label,BRANCH_RELOCATION);
+
+ as_b();
+ as_branch_label (&call_and_jump->cj_jump_label,BRANCH_RELOCATION);
+ }
+}
+
+static void as_rts_begin (struct instruction *instruction)
+{
+ LONG b_offset;
+
+ if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT)
+ as_lwz (REGISTER_R0,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ else
+ as_mr (REGISTER_R0,instruction->instruction_parameters[0].parameter_data.reg.r);
+
+ b_offset=instruction->instruction_parameters[1].parameter_data.i;
+ if (b_offset!=0){
+ if (b_offset!=(WORD) b_offset){
+ as_addis (B_STACK_POINTER,B_STACK_POINTER,(b_offset-(WORD)b_offset)>>16);
+
+ b_offset=(WORD)b_offset;
+ }
+
+ as_addi (B_STACK_POINTER,B_STACK_POINTER,b_offset);
+ }
+}
+
+static void as_rts_instruction (struct instruction *instruction)
+{
+ if (instruction->instruction_arity>0)
+ as_rts_begin (instruction);
+
+ as_blr();
+}
+
+static void as_rtsp_instruction (struct instruction *instruction)
+{
+ as_rts_begin (instruction);
+
+ as_b();
+ as_branch_label (profile_r_label,BRANCH_RELOCATION);
+}
+
+static struct call_and_jump *allocate_new_call_and_jump (void)
+{
+ struct call_and_jump *new_call_and_jump;
+
+ new_call_and_jump=allocate_memory_from_heap_type (struct call_and_jump);
+
+ new_call_and_jump->cj_next=NULL;
+
+ 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;
+
+ return new_call_and_jump;
+}
+
+static void as_branch_instruction (struct instruction *instruction,int i_code)
+{
+ if (instruction->instruction_parameters[0].parameter_type!=P_LABEL)
+ internal_error_in_function ("as_branch_instruction");
+ else {
+ LABEL *label;
+
+ label=instruction->instruction_parameters[0].parameter_data.l;
+
+ as_bc (i_code);
+
+ if (label->label_flags & FAR_CONDITIONAL_JUMP_LABEL){
+ struct call_and_jump *new_call_and_jump;
+
+ new_call_and_jump=allocate_new_call_and_jump();
+
+ new_call_and_jump->cj_call_label=label;
+ new_call_and_jump->cj_label.label_flags=0;
+
+ as_branch_label (&new_call_and_jump->cj_label,CONDITIONAL_BRANCH_RELOCATION);
+
+ new_call_and_jump->cj_jump_label.label_object_label=code_csect_object_label;
+ new_call_and_jump->cj_jump_label.label_flags=FAR_CONDITIONAL_JUMP_LABEL;
+ } else
+ as_branch_label (label,CONDITIONAL_BRANCH_RELOCATION);
+ }
+}
+
+static void as_branchno_instruction (struct instruction *instruction)
+{
+ if (instruction->instruction_parameters[0].parameter_type!=P_LABEL)
+ internal_error_in_function ("as_branchno_instruction");
+ else {
+ LABEL *label;
+
+ label=instruction->instruction_parameters[0].parameter_data.l;
+
+ as_bc ((4<<21)|(3<<16)); /* bns */
+
+ if (label->label_flags & FAR_CONDITIONAL_JUMP_LABEL){
+ struct call_and_jump *new_call_and_jump;
+
+ new_call_and_jump=allocate_new_call_and_jump();
+
+ new_call_and_jump->cj_call_label=label;
+ new_call_and_jump->cj_label.label_flags=0;
+
+ label=&new_call_and_jump->cj_label;
+
+ new_call_and_jump->cj_jump_label.label_object_label=code_csect_object_label;
+ new_call_and_jump->cj_jump_label.label_flags=FAR_CONDITIONAL_JUMP_LABEL;
+ }
+
+ as_branch_label (label,CONDITIONAL_BRANCH_RELOCATION);
+
+ as_mcrxr (0);
+
+ as_bc ((4<<21)|(1<<16)); /* bng */
+ as_branch_label (label,CONDITIONAL_BRANCH_RELOCATION);
+ }
+}
+
+static void as_brancho_instruction (struct instruction *instruction)
+{
+ if (instruction->instruction_parameters[0].parameter_type!=P_LABEL)
+ internal_error_in_function ("as_branchno_instruction");
+ else {
+ LABEL *label;
+
+ label=instruction->instruction_parameters[0].parameter_data.l;
+
+ as_bc ((4<<21)|(3<<16)|12); /* bns */
+
+ if (label->label_flags & FAR_CONDITIONAL_JUMP_LABEL){
+ struct call_and_jump *new_call_and_jump;
+
+ new_call_and_jump=allocate_new_call_and_jump();
+
+ new_call_and_jump->cj_call_label=label;
+ new_call_and_jump->cj_label.label_flags=0;
+
+ label=&new_call_and_jump->cj_label;
+
+ new_call_and_jump->cj_jump_label.label_object_label=code_csect_object_label;
+ new_call_and_jump->cj_jump_label.label_flags=FAR_CONDITIONAL_JUMP_LABEL;
+ }
+
+ as_mcrxr (0);
+
+ as_bc ((12<<21)|(1<<16)); /* bgt */
+ as_branch_label (label,CONDITIONAL_BRANCH_RELOCATION);
+ }
+}
+
+static void as_index_error_branch_instruction (struct instruction *instruction)
+{
+ as_bc ((13<<21)|(0<<16)|8); /* blt+ */
+ as_b();
+ as_branch_label (instruction->instruction_parameters[0].parameter_data.l,BRANCH_RELOCATION);
+}
+
+static void as_set_condition_instruction (struct instruction *instruction,int i_code)
+{
+ as_li (instruction->instruction_parameters[0].parameter_data.reg.r,0);
+ store_instruction ((16<<26)|i_code|8);
+ as_li (instruction->instruction_parameters[0].parameter_data.reg.r,-1);
+}
+
+static void as_setno_condition_instruction (struct instruction *instruction)
+{
+ as_li (instruction->instruction_parameters[0].parameter_data.reg.r,0);
+
+ as_bc ((4<<21)|(3<<16)|12); /* bns */
+ as_mcrxr (0);
+ as_bc ((12<<21)|(1<<16)|8); /* bgt */
+
+ as_li (instruction->instruction_parameters[0].parameter_data.reg.r,-1);
+}
+
+static void as_seto_condition_instruction (struct instruction *instruction)
+{
+ as_li (instruction->instruction_parameters[0].parameter_data.reg.r,0);
+
+ as_bc ((4<<21)|(3<<16)|16); /* bns */
+ as_mcrxr (0);
+ as_bc ((4<<21)|(1<<16)|8); /* bng */
+
+ as_li (instruction->instruction_parameters[0].parameter_data.reg.r,-1);
+}
+
+static void as_load_float_immediate (double float_value,int fp_reg)
+{
+ struct label *new_label;
+
+ as_new_data_module();
+
+ new_label=allocate_memory_from_heap_type (struct label);
+
+ new_label->label_flags=DATA_LABEL;
+ new_label->label_object_label=data_csect_object_label;
+ new_label->label_offset=CURRENT_DATA_OFFSET;
+
+ new_label->label_number=next_label_id++;
+
+ store_long_word_in_data_section (((ULONG*)&float_value)[0]);
+ store_long_word_in_data_section (((ULONG*)&float_value)[1]);
+
+ as_load_label (new_label,0,REGISTER_O0);
+ as_lfd (fp_reg+14,0,REGISTER_O0);
+}
+
+static int as_float_parameter (struct parameter parameter)
+{
+ switch (parameter.parameter_type){
+ case P_F_IMMEDIATE:
+ as_load_float_immediate (*parameter.parameter_data.r,17);
+ return 17;
+ case P_INDIRECT:
+ as_lfd (31,parameter.parameter_offset,parameter.parameter_data.reg.r);
+ return 17;
+ case P_INDEXED:
+ as_lfdx (31,parameter.parameter_data.ir->a_reg.r,parameter.parameter_data.ir->d_reg.r);
+ return 17;
+ case P_F_REGISTER:
+ return parameter.parameter_data.reg.r;
+ default:
+ internal_error_in_function ("as_float_parameter");
+ return 17;
+ }
+}
+
+static void as_fadd_instruction (struct instruction *instruction)
+{
+ int freg;
+
+ freg=as_float_parameter (instruction->instruction_parameters[0]);
+
+ as_fadd (instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ instruction->instruction_parameters[1].parameter_data.reg.r+14,freg+14);
+}
+
+static void as_fdiv_instruction (struct instruction *instruction)
+{
+ int freg;
+
+ freg=as_float_parameter (instruction->instruction_parameters[0]);
+
+#ifdef FSUB_FDIV_REVERSED
+ if (instruction->instruction_parameters[1].parameter_flags)
+ as_fdiv (instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ freg+14,instruction->instruction_parameters[1].parameter_data.reg.r+14);
+ else
+#endif
+ as_fdiv (instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ instruction->instruction_parameters[1].parameter_data.reg.r+14,freg+14);
+}
+
+static void as_fsub_instruction (struct instruction *instruction)
+{
+ int freg;
+
+ freg=as_float_parameter (instruction->instruction_parameters[0]);
+
+#ifdef FSUB_FDIV_REVERSED
+ if (instruction->instruction_parameters[1].parameter_flags)
+ as_fsub (instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ freg+14,instruction->instruction_parameters[1].parameter_data.reg.r+14);
+ else
+#endif
+ as_fsub (instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ instruction->instruction_parameters[1].parameter_data.reg.r+14,freg+14);
+}
+
+#ifdef FMADD
+#define FP_REG_LAST_USE 4
+
+static struct instruction * as_fmul_instruction (struct instruction *instruction)
+#else
+static void as_fmul_instruction (struct instruction *instruction)
+#endif
+{
+ int freg;
+
+ freg=as_float_parameter (instruction->instruction_parameters[0]);
+
+#ifdef FMADD
+ {
+ struct instruction *next_instruction;
+
+ next_instruction=instruction->instruction_next;
+ if (fmadd_flag && next_instruction!=NULL)
+ if (next_instruction->instruction_icode==IFADD){
+ if (next_instruction->instruction_parameters[0].parameter_type==P_F_REGISTER &&
+ next_instruction->instruction_parameters[0].parameter_data.reg.r!=next_instruction->instruction_parameters[1].parameter_data.reg.r)
+ {
+ if (next_instruction->instruction_parameters[0].parameter_data.reg.r==instruction->instruction_parameters[1].parameter_data.reg.r &&
+ next_instruction->instruction_parameters[0].parameter_flags & FP_REG_LAST_USE)
+ {
+ as_fmadd ( next_instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ freg+14,
+ instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ next_instruction->instruction_parameters[1].parameter_data.reg.r+14);
+
+ return next_instruction;
+ } else if (next_instruction->instruction_parameters[1].parameter_data.reg.r==instruction->instruction_parameters[1].parameter_data.reg.r){
+ as_fmadd ( next_instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ freg+14,
+ instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ next_instruction->instruction_parameters[0].parameter_data.reg.r+14);
+
+ return next_instruction;
+ }
+ }
+ } else if (next_instruction->instruction_icode==IFSUB){
+ if (next_instruction->instruction_parameters[0].parameter_type==P_F_REGISTER &&
+ next_instruction->instruction_parameters[0].parameter_data.reg.r!=next_instruction->instruction_parameters[1].parameter_data.reg.r)
+ {
+ if (next_instruction->instruction_parameters[0].parameter_flags & FP_REG_LAST_USE &&
+ next_instruction->instruction_parameters[0].parameter_data.reg.r==instruction->instruction_parameters[1].parameter_data.reg.r)
+ {
+# ifdef FSUB_FDIV_REVERSED
+ if (next_instruction->instruction_parameters[1].parameter_flags)
+ as_fmsub ( next_instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ freg+14,
+ instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ next_instruction->instruction_parameters[1].parameter_data.reg.r+14);
+ else
+# endif
+ as_fnmsub ( next_instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ freg+14,
+ instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ next_instruction->instruction_parameters[1].parameter_data.reg.r+14);
+
+ return next_instruction;
+ } else if (next_instruction->instruction_parameters[1].parameter_data.reg.r==instruction->instruction_parameters[1].parameter_data.reg.r)
+ {
+# ifdef FSUB_FDIV_REVERSED
+ if (next_instruction->instruction_parameters[1].parameter_flags)
+ as_fnmsub ( next_instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ freg+14,
+ instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ next_instruction->instruction_parameters[0].parameter_data.reg.r+14);
+ else
+# endif
+ as_fmsub ( next_instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ freg+14,
+ instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ next_instruction->instruction_parameters[0].parameter_data.reg.r+14);
+ return next_instruction;
+ }
+ }
+ }
+ }
+#endif
+
+ as_fmul (instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ instruction->instruction_parameters[1].parameter_data.reg.r+14,freg+14);
+#ifdef FMADD
+ return instruction;
+#endif
+}
+
+static void as_fneg_instruction (struct instruction *instruction)
+{
+ int freg;
+
+ freg=as_float_parameter (instruction->instruction_parameters[0]);
+
+ as_fneg (instruction->instruction_parameters[1].parameter_data.reg.r+14,freg+14);
+}
+
+static void as_compare_float_instruction (struct instruction *instruction)
+{
+ int freg;
+
+ freg=as_float_parameter (instruction->instruction_parameters[0]);
+
+ as_fcmpu (instruction->instruction_parameters[1].parameter_data.reg.r+14,freg+14);
+}
+
+static struct instruction *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:
+ {
+ struct instruction *next_instruction;
+ int reg0,reg1;
+
+ reg0=instruction->instruction_parameters[0].parameter_data.reg.r;
+ reg1=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ next_instruction=instruction->instruction_next;
+ if (next_instruction)
+ switch (next_instruction->instruction_icode){
+ case IFADD: case IFSUB: case IFMUL: case IFDIV:
+ if (next_instruction->instruction_parameters[1].parameter_data.reg.r==reg1)
+ {
+ int reg_s;
+
+ reg_s=as_float_parameter (next_instruction->instruction_parameters[0]);
+
+ if (reg_s==reg1)
+ reg_s=reg0;
+
+ switch (next_instruction->instruction_icode){
+ case IFADD:
+ as_fadd (reg1+14,reg0+14,reg_s+14);
+ break;
+ case IFSUB:
+#ifdef FSUB_FDIV_REVERSED
+ if (next_instruction->instruction_parameters[1].parameter_flags)
+ as_fsub (reg1+14,reg_s+14,reg0+14);
+ else
+#endif
+ as_fsub (reg1+14,reg0+14,reg_s+14);
+ break;
+ case IFMUL:
+#ifdef FMADD
+ {
+ struct instruction *next_of_next_instruction;
+
+ next_of_next_instruction=next_instruction->instruction_next;
+ if (fmadd_flag && next_of_next_instruction!=NULL){
+ if (next_of_next_instruction->instruction_icode==IFADD){
+ if (next_of_next_instruction->instruction_parameters[0].parameter_type==P_F_REGISTER &&
+ next_of_next_instruction->instruction_parameters[0].parameter_data.reg.r==reg1 &&
+ next_of_next_instruction->instruction_parameters[0].parameter_flags & FP_REG_LAST_USE &&
+ next_of_next_instruction->instruction_parameters[1].parameter_data.reg.r!=reg1)
+ {
+ as_fmadd ( next_of_next_instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ reg0+14,reg_s+14,
+ next_of_next_instruction->instruction_parameters[1].parameter_data.reg.r+14);
+
+ return next_of_next_instruction;
+ }
+ } else if (next_of_next_instruction->instruction_icode==IFSUB &&
+ next_of_next_instruction->instruction_parameters[0].parameter_type==P_F_REGISTER &&
+ next_of_next_instruction->instruction_parameters[0].parameter_data.reg.r!=next_of_next_instruction->instruction_parameters[1].parameter_data.reg.r)
+ {
+ if (next_of_next_instruction->instruction_parameters[0].parameter_flags & FP_REG_LAST_USE &&
+ next_of_next_instruction->instruction_parameters[0].parameter_data.reg.r==reg1)
+ {
+# ifdef FSUB_FDIV_REVERSED
+ if (next_of_next_instruction->instruction_parameters[1].parameter_flags)
+ as_fmsub ( next_of_next_instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ reg0+14,reg_s+14,
+ next_of_next_instruction->instruction_parameters[1].parameter_data.reg.r+14);
+ else
+# endif
+ as_fnmsub ( next_of_next_instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ reg0+14,reg_s+14,
+ next_of_next_instruction->instruction_parameters[1].parameter_data.reg.r+14);
+
+ return next_of_next_instruction;
+ } else if (next_of_next_instruction->instruction_parameters[1].parameter_data.reg.r==reg1){
+# ifdef FSUB_FDIV_REVERSED
+ if (next_of_next_instruction->instruction_parameters[1].parameter_flags)
+ as_fnmsub ( next_of_next_instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ reg0+14,reg_s+14,
+ next_of_next_instruction->instruction_parameters[0].parameter_data.reg.r+14);
+ else
+# endif
+ as_fmsub ( next_of_next_instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ reg0+14,reg_s+14,
+ next_of_next_instruction->instruction_parameters[0].parameter_data.reg.r+14);
+
+ return next_of_next_instruction;
+ }
+ }
+
+ }
+ }
+#endif
+ as_fmul (reg1+14,reg0+14,reg_s+14);
+ break;
+ case IFDIV:
+#ifdef FSUB_FDIV_REVERSED
+ if (next_instruction->instruction_parameters[1].parameter_flags)
+ as_fdiv (reg1+14,reg_s+14,reg0+14);
+ else
+#endif
+ as_fdiv (reg1+14,reg0+14,reg_s+14);
+ break;
+ }
+ return next_instruction;
+ }
+ }
+
+ as_fmr (reg1+14,reg0+14);
+ return instruction;
+ }
+ case P_INDIRECT:
+ as_lfd (instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ return instruction;
+ case P_F_IMMEDIATE:
+ as_load_float_immediate (*instruction->instruction_parameters[0].parameter_data.r,instruction->instruction_parameters[1].parameter_data.reg.r);
+ return instruction;
+ case P_INDEXED:
+ as_lfdx (instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ instruction->instruction_parameters[0].parameter_data.ir->a_reg.r,
+ instruction->instruction_parameters[0].parameter_data.ir->d_reg.r);
+ return instruction;
+ }
+ break;
+ case P_INDIRECT:
+ if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){
+ as_stfd (instruction->instruction_parameters[0].parameter_data.reg.r+14,
+ instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return instruction;
+ }
+ break;
+ case P_INDEXED:
+ if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){
+ as_stfdx (instruction->instruction_parameters[0].parameter_data.reg.r+14,
+ instruction->instruction_parameters[1].parameter_data.ir->a_reg.r,
+ instruction->instruction_parameters[1].parameter_data.ir->d_reg.r);
+ return instruction;
+ }
+ break;
+
+ }
+ internal_error_in_function ("w_as_fmove_instruction");
+ return instruction;
+}
+
+static void as_btst_instruction (struct instruction *instruction)
+{
+ as_andi_ (REGISTER_O0,instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[0].parameter_data.i);
+}
+
+extern LABEL *r_to_i_buffer_label;
+
+static void 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)
+ internal_error_in_function ("as_fmovel_instruction");
+
+ as_fctiw (31,instruction->instruction_parameters[0].parameter_data.reg.r+14);
+ as_load_label (r_to_i_buffer_label,0,REGISTER_O0);
+ as_stfd (31,0,REGISTER_O0);
+ as_lwz (instruction->instruction_parameters[1].parameter_data.reg.r,4,REGISTER_O0);
+ } else {
+ int reg;
+ struct label *new_label;
+
+ reg=as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ as_new_data_module();
+
+ new_label=allocate_memory_from_heap_type (struct label);
+
+ new_label->label_flags=DATA_LABEL;
+ new_label->label_object_label=data_csect_object_label;
+ new_label->label_offset=CURRENT_DATA_OFFSET;
+
+ new_label->label_number=next_label_id++;
+
+ store_long_word_in_data_section (0x43300000);
+ store_long_word_in_data_section (0x00000000);
+ store_long_word_in_data_section (0x43300000);
+ store_long_word_in_data_section (0x80000000);
+
+ /*
+ lwz o1,t_n{TC}(RTOC)
+ xoris o0,reg,0x8000
+ lfd fp31,8(o1)
+ stw o0,4(o1)
+ lfd freg,0(o1)
+ fsub freg,freg,fp31
+ */
+
+ as_load_label (new_label,0,REGISTER_O1);
+ as_xoris (REGISTER_O0,reg,0x8000);
+ as_lfd (31,8,REGISTER_O1);
+ as_stw (REGISTER_O0,4,REGISTER_O1);
+ as_lfd (instruction->instruction_parameters[1].parameter_data.reg.r+14,0,REGISTER_O1);
+ as_fsub (instruction->instruction_parameters[1].parameter_data.reg.r+14,
+ instruction->instruction_parameters[1].parameter_data.reg.r+14,31);
+ }
+}
+
+static void write_instructions (struct instruction *instructions)
+{
+ struct instruction *instruction;
+
+ for_l (instruction,instructions,instruction_next){
+ switch (instruction->instruction_icode){
+ case IMOVE:
+ as_move_instruction (instruction,SIZE_LONG);
+ break;
+ case ILEA:
+ as_lea_instruction (instruction);
+ break;
+ case IADD:
+ as_add_instruction (instruction);
+ break;
+ case IADDI:
+ as_addi_instruction (instruction);
+ break;
+ case ISUB:
+ as_sub_instruction (instruction);
+ break;
+ case ICMP:
+ as_cmp_instruction (instruction,SIZE_LONG);
+ break;
+ case IJMP:
+ as_jmp_instruction (instruction);
+ break;
+ case IJSR:
+ as_jsr_instruction (instruction);
+ break;
+ case IRTS:
+ as_rts_instruction (instruction);
+ break;
+ case IBEQ:
+ case IFBEQ:
+ as_branch_instruction (instruction,(12<<21)|(2<<16));
+ break;
+ case IBGE:
+ case IFBGE:
+ as_branch_instruction (instruction,(4<<21)|(0<<16));
+ break;
+ case IBGT:
+ case IFBGT:
+ as_branch_instruction (instruction,(12<<21)|(1<<16));
+ break;
+ case IBLE:
+ case IFBLE:
+ as_branch_instruction (instruction,(4<<21)|(1<<16));
+ break;
+ case IBLT:
+ case IFBLT:
+ as_branch_instruction (instruction,(12<<21)|(0<<16));
+ break;
+ case IBNE:
+ case IFBNE:
+ as_branch_instruction (instruction,(4<<21)|(2<<16));
+ break;
+ case IBNEP:
+ as_branch_instruction (instruction,(5<<21)|(2<<16));
+ break;
+ case IBHS:
+ as_index_error_branch_instruction (instruction);
+ break;
+ case IBNO:
+ as_branchno_instruction (instruction);
+ break;
+ case IBO:
+ as_brancho_instruction (instruction);
+ break;
+ case ICMPLW:
+ as_cmplw_instruction (instruction);
+ break;
+ case ILSLI:
+ as_slwi_instruction (instruction);
+ break;
+ case ILSL:
+ as_slw_instruction (instruction);
+ break;
+ case ILSR:
+ as_srw_instruction (instruction);
+ break;
+ case IASR:
+ as_sraw_instruction (instruction);
+ break;
+ case IMUL:
+ as_mul_instruction (instruction);
+ break;
+ case IDIV:
+ as_div_instruction (instruction);
+ break;
+ case IMOD:
+ as_rem_instruction (instruction);
+ break;
+ case IAND:
+ as_and_instruction (instruction);
+ break;
+ case IOR:
+ as_or_instruction (instruction);
+ break;
+ case IEOR:
+ as_xor_instruction (instruction);
+ break;
+ case ISEQ:
+ case IFSEQ:
+ as_set_condition_instruction (instruction,(4<<21)|(2<<16));
+ break;
+ case ISGE:
+ case IFSGE:
+ as_set_condition_instruction (instruction,(12<<21)|(0<<16));
+ break;
+ case ISGT:
+ case IFSGT:
+ as_set_condition_instruction (instruction,(4<<21)|(1<<16));
+ break;
+ case ISLE:
+ case IFSLE:
+ as_set_condition_instruction (instruction,(12<<21)|(1<<16));
+ break;
+ case ISLT:
+ case IFSLT:
+ as_set_condition_instruction (instruction,(4<<21)|(0<<16));
+ break;
+ case ISNE:
+ case IFSNE:
+ as_set_condition_instruction (instruction,(12<<21)|(2<<16));
+ break;
+ case ISNO:
+ as_setno_condition_instruction (instruction);
+ break;
+ case ISO:
+ as_seto_condition_instruction (instruction);
+ break;
+ case ICMPW:
+ as_cmp_instruction (instruction,SIZE_WORD);
+ break;
+ case ITST:
+ as_tst_instruction (instruction);
+ break;
+ case IBTST:
+ as_btst_instruction (instruction);
+ break;
+ case IMOVEW:
+ as_move_instruction (instruction,SIZE_WORD);
+ break;
+ case IMOVEB:
+ as_move_instruction (instruction,SIZE_BYTE);
+ break;
+ case IEXTB:
+ as_extb_instruction (instruction);
+ break;
+ case IFMOVE:
+ instruction=as_fmove_instruction (instruction);
+ break;
+ case IFADD:
+ as_fadd_instruction (instruction);
+ break;
+ case IFCMP:
+ as_compare_float_instruction (instruction);
+ break;
+ case IFDIV:
+ as_fdiv_instruction (instruction);
+ break;
+ case IFMUL:
+#ifdef FMADD
+ instruction=as_fmul_instruction (instruction);
+#else
+ as_fmul_instruction (instruction);
+#endif
+ break;
+ case IFNEG:
+ as_fneg_instruction (instruction);
+ break;
+ case IFSUB:
+ as_fsub_instruction (instruction);
+ break;
+ case IFMOVEL:
+ as_fmovel_instruction (instruction);
+ break;
+ case IWORD:
+ store_instruction (instruction->instruction_parameters[0].parameter_data.i);
+ break;
+ case IMTCTR:
+ as_mtctr (instruction->instruction_parameters[0].parameter_data.reg.r);
+ break;
+ case IJMPP:
+ as_jmpp_instruction (instruction);
+ break;
+ case IRTSP:
+ as_rtsp_instruction (instruction);
+ break;
+ case IADDO:
+ as_addo_instruction (instruction);
+ break;
+ case ISUBO:
+ as_subo_instruction (instruction);
+ break;
+ case IMULO:
+ as_mulo_instruction (instruction);
+ break;
+ default:
+ internal_error_in_function ("write_instructions");
+ }
+ }
+}
+
+static void as_garbage_collect_test (register struct basic_block *block)
+{
+ LONG n_cells;
+ struct call_and_jump *new_call_and_jump;
+
+ new_call_and_jump=allocate_new_call_and_jump();
+
+ n_cells= -block->block_n_new_heap_cells;
+
+ if (n_cells!=(WORD) n_cells){
+ as_addis (REGISTER_D7,REGISTER_D7,(n_cells-(WORD)n_cells)>>16);
+ n_cells=(WORD)n_cells;
+ }
+
+ as_addic_ (REGISTER_D7,REGISTER_D7,n_cells);
+
+#ifdef USE_DCBZ
+ as_dcbz (REGISTER_A6,REGISTER_R9);
+#endif
+
+ if (block->block_gc_kind!=0){
+ switch (block->block_n_begin_a_parameter_registers){
+ case 0: new_call_and_jump->cj_call_label=collect_00_label; break;
+ case 1: new_call_and_jump->cj_call_label=collect_01_label; break;
+ case 2: new_call_and_jump->cj_call_label=collect_02_label; break;
+ case 3: new_call_and_jump->cj_call_label=collect_03_label; break;
+ default: internal_error_in_function ("as_garbage_collect_test");
+ }
+ new_call_and_jump->cj_label.label_flags=0;
+
+ if (block->block_gc_kind==2)
+ as_mflr (REGISTER_R0);
+
+ as_bc ((12/* 13 */<<21)|(0<<16)|1); /* bltl */
+ as_branch_label (&new_call_and_jump->cj_label,CONDITIONAL_BRANCH_RELOCATION);
+
+ if (block->block_gc_kind==1)
+ as_mtlr (REGISTER_R0);
+
+ new_call_and_jump->cj_jump_label.label_object_label=code_csect_object_label;
+ new_call_and_jump->cj_jump_label.label_flags=FAR_CONDITIONAL_JUMP_LABEL;
+ } else {
+ switch (block->block_n_begin_a_parameter_registers){
+ case 0: new_call_and_jump->cj_call_label=collect_0_label; break;
+ case 1: new_call_and_jump->cj_call_label=collect_1_label; break;
+ case 2: new_call_and_jump->cj_call_label=collect_2_label; break;
+ case 3: new_call_and_jump->cj_call_label=collect_3_label; break;
+ default: internal_error_in_function ("as_garbage_collect_test");
+ }
+ new_call_and_jump->cj_label.label_flags=0;
+
+ as_bc ((12<<21)|(0<<16)); /* blt */
+ as_branch_label (&new_call_and_jump->cj_label,CONDITIONAL_BRANCH_RELOCATION);
+
+ new_call_and_jump->cj_jump_label.label_flags=0;
+ new_call_and_jump->cj_jump_label.label_object_label=code_csect_object_label;
+ new_call_and_jump->cj_jump_label.label_offset=CURRENT_CODE_OFFSET;
+ }
+}
+
+static void as_check_stack (struct basic_block *block)
+{
+#ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS
+ if (block->block_a_stack_check_size>0){
+ as_load_label (end_a_stack_label,0,REGISTER_O0);
+
+ as_addi (REGISTER_O1,A_STACK_POINTER,block->block_a_stack_check_size);
+
+ as_lwz (REGISTER_O0,0,REGISTER_O0);
+ as_cmp (REGISTER_O1,REGISTER_O0);
+
+ as_bc ((5<<21)|(1<<16)|8); /* ble+ */
+ as_b();
+ as_branch_label (stack_overflow_label,BRANCH_RELOCATION);
+ }
+ if (block->block_b_stack_check_size>0){
+ as_load_label (end_b_stack_label,0,REGISTER_O0);
+
+ as_addi (REGISTER_O1,B_STACK_POINTER,-block->block_b_stack_check_size);
+
+ as_lwz (REGISTER_O0,0,REGISTER_O0);
+ as_cmp (REGISTER_O1,REGISTER_O0);
+
+ as_bc ((13<<21)|(1<<16)|8); /* bgt+ */
+ as_b();
+ as_branch_label (stack_overflow_label,BRANCH_RELOCATION);
+ }
+#else
+ int size;
+
+ size=block->block_stack_check_size+1024;
+
+ as_sub (REGISTER_O0,B_STACK_POINTER,A_STACK_POINTER);
+ as_cmpi (REGISTER_O0,size);
+ as_bc ((13<<21)|(1<<16)|8); /* bgt+ */
+ as_b();
+ as_branch_label (stack_overflow_label,BRANCH_RELOCATION);
+#endif
+}
+
+static void as_import_labels (struct label_node *label_node)
+{
+ LABEL *label;
+
+ if (label_node==NULL)
+ return;
+
+ label=&label_node->label_node_label;
+
+ if (!(label->label_flags & LOCAL_LABEL) && label->label_number==0){
+ struct object_label *new_object_label;
+ int string_length;
+
+ new_object_label=fast_memory_allocate_type (struct object_label);
+ *last_object_label_l=new_object_label;
+ last_object_label_l=&new_object_label->next;
+ new_object_label->next=NULL;
+
+ new_object_label->object_label_label=label;
+ new_object_label->object_label_number=n_object_labels;
+
+ label->label_object_label=new_object_label;
+ label->label_offset=0;
+
+ ++n_object_labels;
+
+ string_length=strlen (label->label_name);
+#ifdef XCOFF
+ if (string_length<8)
+ new_object_label->object_label_string_offset=0;
+ else {
+#endif
+ new_object_label->object_label_string_offset=string_table_offset;
+ string_table_offset+=string_length+1;
+#ifdef XCOFF
+ }
+#endif
+
+ new_object_label->kind=IMPORTED_CODE_LABEL;
+ }
+
+ as_import_labels (label_node->label_node_left);
+ as_import_labels (label_node->label_node_right);
+}
+
+static void write_code (void)
+{
+ struct basic_block *block;
+
+ first_call_and_jump=NULL;
+#ifdef G_MACH_O
+ first_stub=NULL;
+ next_stub_l=&first_stub;
+ n_stubs=0;
+#endif
+
+ if (!(first_block->block_begin_module && !first_block->block_link_module))
+ as_new_code_module();
+
+ for_l (block,first_block,block_next){
+ if (block->block_begin_module){
+ if (block->block_link_module){
+#ifdef XCOFF
+ if (code_csect_object_label!=NULL
+ && CURRENT_CODE_OFFSET!=code_csect_object_label->object_label_offset
+ && block->block_labels)
+ {
+ as_branch_label (block->block_labels->block_label_label,DUMMY_CONDITIONAL_BRANCH_RELOCATION);
+ as_new_code_module();
+ }
+#endif
+ } else {
+ if (first_call_and_jump!=NULL){
+ struct call_and_jump *call_and_jump;
+ struct object_label *gc_test_csect_object_label;
+
+ gc_test_csect_object_label=code_csect_object_label;
+
+ for_l (call_and_jump,first_call_and_jump,cj_next){
+ if (call_and_jump->cj_jump_label.label_object_label!=gc_test_csect_object_label){
+ as_new_code_module();
+ gc_test_csect_object_label=call_and_jump->cj_jump_label.label_object_label;
+ }
+ as_call_and_jump (call_and_jump);
+ }
+
+ first_call_and_jump=NULL;
+ }
+
+ as_new_code_module();
+ }
+ }
+
+ if (block->block_n_node_arguments>-100){
+ if (block->block_ea_label!=NULL){
+ int n_node_arguments;
+ extern LABEL *eval_fill_label,*eval_upd_labels[];
+
+ 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){
+ as_load_label (block->block_ea_label,0,REGISTER_A2);
+
+ if (!block->block_profile){
+ as_b();
+ as_branch_label (eval_upd_labels[n_node_arguments],BRANCH_RELOCATION);
+
+ as_nop();
+#if defined (ELF) || defined (G_MACH_O)
+ as_nop();
+#endif
+ } else {
+ if (profile_table_flag){
+ store_instruction ((18<<26) | ((-8) & 0x3fffffc));
+ as_branch_label (eval_upd_labels[n_node_arguments],BRANCH_RELOCATION);
+
+ as_load_label (profile_table_label,32764,REGISTER_R3);
+ as_addi (REGISTER_R3,REGISTER_R3,block->block_profile_function_label->label_arity-32764);
+ store_instruction ((18<<26)|(-16 & 0x3fffffc));
+ } else {
+ as_load_label (block->block_profile_function_label,0,REGISTER_R3);
+
+ store_instruction ((18<<26) | ((-8) & 0x3fffffc));
+ as_branch_label (eval_upd_labels[n_node_arguments],BRANCH_RELOCATION);
+ }
+ }
+ } else {
+ as_b();
+ as_branch_label (block->block_ea_label,BRANCH_RELOCATION);
+
+ as_nop();
+ as_nop();
+#if defined (ELF) || defined (G_MACH_O)
+ as_nop();
+ as_nop();
+#endif
+ }
+
+ if (block->block_descriptor!=NULL &&
+ (block->block_n_node_arguments<0 || parallel_flag || module_info_flag))
+ {
+#if defined (ELF) || defined (G_MACH_O)
+ store_label_in_code_section (block->block_descriptor,0);
+#else
+ as_load_label1 (block->block_descriptor,0,REGISTER_R0,TOC_RELOCATION);
+#endif
+ /* store_instruction (0); */
+ } else
+ store_instruction (0);
+ } else
+ if (block->block_descriptor!=NULL &&
+ (block->block_n_node_arguments<0 || parallel_flag || module_info_flag))
+ {
+#if defined (ELF) || defined (G_MACH_O)
+ store_label_in_code_section (block->block_descriptor,0);
+#else
+ as_load_label1 (block->block_descriptor,0,REGISTER_R0,TOC_RELOCATION);
+#endif
+ /* store_instruction (0); */
+ }
+ /* else
+ store_instruction (0);
+ */
+
+ store_instruction (block->block_n_node_arguments);
+ }
+
+ as_labels (block->block_labels);
+
+ if (block->block_profile){
+ LABEL *profile_label;
+
+ if (profile_table_flag){
+ as_load_label (profile_table_label,32764,REGISTER_R3);
+ as_mflr (REGISTER_R0);
+ as_addi (REGISTER_R3,REGISTER_R3,block->block_profile_function_label->label_arity-32764);
+ } else {
+ as_load_label (block->block_profile_function_label,0,REGISTER_R3);
+ as_mflr (REGISTER_R0);
+ }
+ as_bl();
+
+ if (block->block_n_node_arguments>-100)
+ profile_label=block->block_profile==2 ? profile_n2_label : profile_n_label;
+ else {
+ switch (block->block_profile){
+ case 2: profile_label=profile_s2_label; break;
+ case 4: profile_label=profile_l_label; break;
+ case 5: profile_label=profile_l2_label; break;
+ default: profile_label=profile_s_label;
+ }
+ }
+ as_branch_label (profile_label,BRANCH_RELOCATION);
+ }
+
+ if (block->block_n_new_heap_cells!=0)
+ as_garbage_collect_test (block);
+
+ if (check_stack
+#ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS
+ && (block->block_a_stack_check_size>0 || block->block_b_stack_check_size>0)
+#else
+ && block->block_stack_check_size>0
+#endif
+ )
+ as_check_stack (block);
+ write_instructions (block->block_instructions);
+ }
+
+ {
+ struct call_and_jump *call_and_jump;
+
+ for_l (call_and_jump,first_call_and_jump,cj_next)
+ as_call_and_jump (call_and_jump);
+ }
+}
+
+void initialize_assembler (FILE *output_file_d)
+{
+ output_file=output_file_d;
+#ifdef ELF
+ n_object_labels=0;
+#else
+ n_object_labels=0;
+#endif
+ setvbuf (output_file,NULL,_IOFBF,IO_BUFFER_SIZE);
+
+ first_object_label=NULL;
+ last_object_label_l=&first_object_label;
+
+ code_csect_object_label=NULL;
+ data_csect_object_label=NULL;
+#ifdef G_MACH_O
+ stub_csect_object_label=NULL;
+#endif
+
+ first_code_relocation=NULL;
+ first_data_relocation=NULL;
+ last_code_relocation_l=&first_code_relocation;
+ last_data_relocation_l=&first_data_relocation;
+ n_code_relocations=0;
+ n_data_relocations=0;
+#ifdef ELF
+ string_table_offset=13;
+#else
+ string_table_offset=4;
+#endif
+ initialize_buffers();
+}
+
+static void relocate_branches (void)
+{
+ struct relocation *relocation,**relocation_p;
+ struct object_buffer *object_buffer;
+ int buffer_offset;
+ struct label *label;
+ int instruction_offset;
+ ULONG *instruction_p;
+
+ object_buffer=first_code_buffer;
+ buffer_offset=0;
+
+ relocation_p=&first_code_relocation;
+
+ while (relocation=*relocation_p,relocation!=NULL){
+ switch (relocation->kind){
+ case CONDITIONAL_BRANCH_RELOCATION:
+ label=relocation->relocation_label;
+ if (label->label_object_label==NULL)
+ internal_error_in_function ("relocate_branches");
+
+ instruction_offset=relocation->offset;
+ while (instruction_offset >= buffer_offset+BUFFER_SIZE){
+ object_buffer=object_buffer->next;
+ buffer_offset+=BUFFER_SIZE;
+ }
+
+ instruction_p=(ULONG*)((char*)(object_buffer->data)+(instruction_offset-buffer_offset));
+
+ *instruction_p= ((*instruction_p)& 0xffff0003) | (label->label_offset-instruction_offset & 0xfffc);
+
+ if (label->label_object_label->object_label_number==relocation->relocation_object_label->object_label_number){
+ *relocation_p=relocation->next;
+ --n_code_relocations;
+ continue;
+ }
+ break;
+ case BRANCH_RELOCATION:
+ label=relocation->relocation_label;
+ if (label->label_object_label==NULL)
+ internal_error_in_function ("relocate_branches");
+
+ instruction_offset=relocation->offset;
+ while (instruction_offset >= buffer_offset+BUFFER_SIZE){
+ object_buffer=object_buffer->next;
+ buffer_offset+=BUFFER_SIZE;
+ }
+
+ instruction_p=(ULONG*)((char*)(object_buffer->data)+(instruction_offset-buffer_offset));
+
+ *instruction_p = ((*instruction_p) & 0xfc000003) | ((*instruction_p+label->label_offset-instruction_offset) & 0x3fffffc);
+
+ if (label->label_object_label->object_label_number==relocation->relocation_object_label->object_label_number){
+ *relocation_p=relocation->next;
+ --n_code_relocations;
+ continue;
+ }
+ break;
+ case DUMMY_CONDITIONAL_BRANCH_RELOCATION:
+ label=relocation->relocation_label;
+ if (label->label_object_label==NULL)
+ internal_error_in_function ("relocate_branches");
+
+ if (label->label_object_label->object_label_number==relocation->relocation_object_label->object_label_number){
+ *relocation_p=relocation->next;
+ --n_code_relocations;
+ continue;
+ }
+ break;
+#ifdef G_MACH_O
+ case HIGH_RELOCATION:
+ {
+ int addend;
+
+ label=relocation->relocation_label;
+ if (label->label_object_label==NULL)
+ internal_error_in_function ("relocate_branches");
+
+ addend=relocation->relocation_addend+label->label_offset;
+ if (label->label_object_label->kind==DATA_CONTROL_SECTION || label->label_object_label->kind==EXPORTED_DATA_LABEL)
+ addend+=code_buffer_offset;
+
+ addend=(addend-(WORD)addend)>>16;
+
+ if (addend!=0){
+ UWORD *instruction_w_p;
+
+ instruction_offset=relocation->offset;
+ while (instruction_offset >= buffer_offset+BUFFER_SIZE){
+ object_buffer=object_buffer->next;
+ buffer_offset+=BUFFER_SIZE;
+ }
+
+ instruction_w_p=(UWORD*)((char*)(object_buffer->data)+(instruction_offset-buffer_offset));
+ instruction_w_p[1]+=addend;
+ }
+ break;
+ }
+ case LOW_RELOCATION:
+ {
+ int addend;
+
+ label=relocation->relocation_label;
+ if (label->label_object_label==NULL)
+ internal_error_in_function ("relocate_branches");
+
+ addend=relocation->relocation_addend+label->label_offset;
+ if (label->label_object_label->kind==DATA_CONTROL_SECTION || label->label_object_label->kind==EXPORTED_DATA_LABEL)
+ addend+=code_buffer_offset;
+
+ addend=((unsigned)addend) & 0xffff;
+
+ if (addend!=0){
+ UWORD *instruction_w_p;
+
+ instruction_offset=relocation->offset;
+ while (instruction_offset >= buffer_offset+BUFFER_SIZE){
+ object_buffer=object_buffer->next;
+ buffer_offset+=BUFFER_SIZE;
+ }
+
+ instruction_w_p=(UWORD*)((char*)(object_buffer->data)+(instruction_offset-buffer_offset));
+ instruction_w_p[1]+=addend;
+ }
+
+ break;
+ }
+ case LONG_WORD_RELOCATION:
+ {
+ int addend;
+
+ label=relocation->relocation_label;
+ if (label->label_object_label==NULL)
+ internal_error_in_function ("relocate_branches");
+
+ addend=relocation->relocation_addend+label->label_offset;
+ if (label->label_object_label->kind==DATA_CONTROL_SECTION || label->label_object_label->kind==EXPORTED_DATA_LABEL)
+ addend+=code_buffer_offset;
+
+ if (addend!=0){
+ int data_offset;
+
+ data_offset=relocation->offset;
+ while (data_offset >= buffer_offset+BUFFER_SIZE){
+ object_buffer=object_buffer->next;
+ buffer_offset+=BUFFER_SIZE;
+ }
+
+ *(ULONG*)((char*)(object_buffer->data)+(data_offset-buffer_offset)) += addend;
+ }
+ break;
+ }
+#endif
+ }
+
+ relocation_p=&relocation->next;
+ }
+}
+
+static void relocate_data (void)
+{
+ struct relocation *relocation;
+ struct object_buffer *object_buffer;
+ int data_buffer_offset;
+
+ object_buffer=first_data_buffer;
+ data_buffer_offset=0;
+
+ for_l (relocation,first_data_relocation,next){
+ struct label *label;
+
+ label=relocation->relocation_label;
+
+ if (label->label_object_label==NULL)
+ internal_error_in_function ("relocate_data");
+#ifdef XCOFF
+ if (relocation->kind==LONG_WORD_RELOCATION && label->label_offset!=0){
+#else
+# ifdef G_MACH_O
+ if (relocation->kind==LONG_WORD_RELOCATION){
+ int addend;
+
+ addend=relocation->relocation_addend+label->label_offset;
+ if (label->label_object_label->kind==DATA_CONTROL_SECTION || label->label_object_label->kind==EXPORTED_DATA_LABEL)
+ addend+=code_buffer_offset;
+ if (addend!=0){
+# else
+ if (relocation->kind==LONG_WORD_RELOCATION && relocation->relocation_addend+label->label_offset!=0){
+# endif
+#endif
+ int data_offset;
+
+ data_offset=relocation->offset;
+ while (data_offset >= data_buffer_offset+BUFFER_SIZE){
+ object_buffer=object_buffer->next;
+ data_buffer_offset+=BUFFER_SIZE;
+ }
+
+#ifdef G_MACH_O
+ *(ULONG*)((char*)(object_buffer->data)+(data_offset-data_buffer_offset)) += addend;
+ }
+#else
+ *(ULONG*)((char*)(object_buffer->data)+(data_offset-data_buffer_offset)) += label->label_offset;
+#endif
+ }
+ }
+}
+
+#ifdef ELF
+static void write_zstring (char *string)
+{
+ char c;
+
+ do {
+ c=*string++;
+ write_c (c);
+ } while (c!='\0');
+}
+#endif
+
+#ifdef G_MACH_O
+static void write_string_16 (char *string)
+{
+ int i;
+
+ i=0;
+
+ while (i<16){
+ char c;
+
+ c=string[i++];
+ write_c (c);
+
+ if (c=='\0'){
+ while (i<16){
+ write_c ('\0');
+ ++i;
+ }
+ return;
+ }
+ }
+}
+#endif
+
+static void write_file_header_and_section_headers (void)
+{
+#ifdef ELF
+ unsigned int offset;
+
+ /* header: */
+ write_l (0x7f454c46);
+ write_l (0x01020100);
+ write_l (0);
+ write_l (0);
+ write_l (0x00010014);
+ write_l (1);
+ write_l (0);
+ write_l (0);
+ write_l (0x34);
+ write_l (0);
+ write_l (0x00340000);
+ write_l (0x00000028);
+ write_l (0x00080001);
+ offset=0x174;
+ /* offet 0x34: section header 0 */
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ /* offset 0x5c: section header 1 */
+ write_l (1); /* .shstrtab offset */
+ write_l (SHT_STRTAB);
+ write_l (0);
+ write_l (0);
+ write_l (offset); /* offset */
+ write_l (64); /* size */
+ write_l (0);
+ write_l (0);
+ write_l (1); /* align */
+ write_l (0);
+ offset+=64;
+ /* offset 0x84: section header 2 */
+ write_l (11); /* .text offset */
+ write_l (SHT_PROGBITS);
+ write_l (SHF_ALLOC | SHF_EXECINSTR);
+ write_l (0);
+ write_l (offset); /* offset */
+ write_l (code_buffer_offset); /* size */
+ write_l (0);
+ write_l (0);
+ write_l (4); /* align */
+ write_l (0);
+ offset+=code_buffer_offset;
+ /* offset 0xac: section header 3 */
+ write_l (17); /* .data offset */
+ write_l (SHT_PROGBITS);
+ write_l (SHF_ALLOC | SHF_WRITE);
+ write_l (0);
+ write_l (offset); /* offset */
+ write_l (data_buffer_offset); /* size */
+ write_l (0);
+ write_l (0);
+ write_l (4); /* align */
+ write_l (0);
+ offset+=data_buffer_offset;
+ /* offet 0xd4: section header 4 */
+ write_l (23); /* .rela.text offset */
+ write_l (SHT_RELA);
+ write_l (0);
+ write_l (0);
+ write_l (offset); /* offset */
+ write_l (12*n_code_relocations); /* size */
+ write_l (6); /* symbol table index */
+ write_l (2); /* text section index */
+ write_l (4); /* align */
+ write_l (12);
+ offset+=12*n_code_relocations;
+ /* offset 0xfc: section header 5 */
+ write_l (34); /* .rela.data offset */
+ write_l (SHT_RELA);
+ write_l (0);
+ write_l (0);
+ write_l (offset); /* offset */
+ write_l (12*n_data_relocations); /* size */
+ write_l (6); /* symbol table index */
+ write_l (3); /* data section index */
+ write_l (4); /* align */
+ write_l (12);
+ offset+=12*n_data_relocations;
+ /* offset 0x124: section header 6 */
+ write_l (45); /* .symtab offset */
+ write_l (SHT_SYMTAB);
+ write_l (0);
+ write_l (0);
+ write_l (offset); /* offset */
+ write_l (16*n_object_labels); /* size */
+ write_l (7); /* string table index */
+ write_l (3);
+ write_l (4); /* align */
+ write_l (16);
+ offset+=16*n_object_labels;
+ /* offset 0x14c: section header 7 */
+ write_l (53); /* .strtab offset */
+ write_l (SHT_STRTAB);
+ write_l (0);
+ write_l (0);
+ write_l (offset); /* offset */
+ write_l (string_table_offset); /* size */
+ write_l (0);
+ write_l (0);
+ write_l (0); /* align */
+ write_l (0);
+
+ /* offset 0x174: section 1 */
+ write_c (0);
+ write_zstring (".shstrtab"); /* 1 */
+ write_zstring (".text"); /* 11 */
+ write_zstring (".data"); /* 17 */
+ write_zstring (".rela.text");/* 23 */
+ write_zstring (".rela.data");/* 34 */
+ write_zstring (".symtab"); /* 45 */
+ write_zstring (".strtab"); /* 53 */
+ /* 61 */
+ write_c (0);
+ write_c (0);
+ write_c (0);
+ /* offset 0x1b4 */
+#else
+# ifdef G_MACH_O
+ int segment_command_size;
+ int text_section_offset,text_section_relocation_offset;
+
+ segment_command_size = n_stubs!=0 ? sizeof (struct segment_command)+4*sizeof (struct section)
+ : sizeof (struct segment_command)+2*sizeof (struct section);
+
+ write_l (MH_MAGIC);
+ write_l (0x12/*PPC*/);
+ write_l (0/*ALL*/);
+ write_l (MH_OBJECT);
+ write_l (3);
+ write_l (segment_command_size+sizeof (struct symtab_command)+sizeof (struct dysymtab_command));
+ write_l (0);
+
+ text_section_offset=sizeof (struct mach_header)+segment_command_size+sizeof (struct symtab_command)+sizeof (struct dysymtab_command);
+
+ write_l (LC_SEGMENT);
+ write_l (segment_command_size);
+ write_string_16 ("\0");
+ write_l (0);
+ write_l (code_buffer_offset+data_buffer_offset+(36+4)*n_stubs);
+ write_l (text_section_offset);
+ write_l (code_buffer_offset+data_buffer_offset+(36+4)*n_stubs);
+ write_l (VM_PROT_ALL);
+ write_l (VM_PROT_ALL);
+ write_l (n_stubs!=0 ? 4 : 2);
+ write_l (0);
+
+ text_section_relocation_offset=text_section_offset+code_buffer_offset+data_buffer_offset+(36+4)*n_stubs;
+
+ write_string_16 ("__text");
+ write_string_16 ("__TEXT");
+ write_l (0);
+ write_l (code_buffer_offset);
+ write_l (text_section_offset);
+ write_l (0);
+ write_l (text_section_relocation_offset);
+ write_l (n_code_relocations);
+ write_l (S_REGULAR | S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS);
+ write_l (0);
+ write_l (0);
+
+ write_string_16 ("__data");
+ write_string_16 ("__DATA");
+ write_l (code_buffer_offset);
+ write_l (data_buffer_offset);
+ write_l (text_section_offset+code_buffer_offset);
+ write_l (0);
+ write_l (text_section_relocation_offset+8*n_code_relocations);
+ write_l (n_data_relocations);
+ write_l (S_REGULAR);
+ write_l (0);
+ write_l (0);
+
+ if (n_stubs!=0){
+ write_string_16 ("__picsymbol_stub");
+ write_string_16 ("__TEXT");
+ write_l (code_buffer_offset+data_buffer_offset);
+ write_l (n_stubs*36);
+ write_l (text_section_offset+code_buffer_offset+data_buffer_offset);
+ write_l (2);
+ write_l (text_section_relocation_offset+8*(n_code_relocations+n_data_relocations));
+ write_l (6*n_stubs);
+ write_l (S_SYMBOL_STUBS | S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS);
+ write_l (0);
+ write_l (36);
+
+ write_string_16 ("__la_symbol_ptr");
+ write_string_16 ("__DATA");
+ write_l (code_buffer_offset+data_buffer_offset+n_stubs*36);
+ write_l (n_stubs<<2);
+ write_l (text_section_offset+code_buffer_offset+data_buffer_offset+n_stubs*36);
+ write_l (2);
+ write_l (text_section_relocation_offset+8*(n_code_relocations+n_data_relocations+6*n_stubs));
+ write_l (n_stubs);
+ write_l (S_LAZY_SYMBOL_POINTERS);
+ write_l (0);
+ write_l (0);
+ }
+
+ write_l (LC_SYMTAB);
+ write_l (sizeof (struct symtab_command));
+ write_l (text_section_relocation_offset+8*(n_code_relocations+n_data_relocations+(6+1+1)*n_stubs));
+ write_l (n_object_labels);
+ write_l (text_section_relocation_offset+8*(n_code_relocations+n_data_relocations+(6+1+1)*n_stubs)+12*n_object_labels);
+ write_l (string_table_offset);
+
+ write_l (LC_DYSYMTAB);
+ write_l (sizeof (struct dysymtab_command));
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_l (n_exported_object_labels);
+ write_l (n_exported_object_labels);
+ write_l (n_object_labels-n_exported_object_labels);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_l (text_section_relocation_offset+8*(n_code_relocations+n_data_relocations+(6+1)*n_stubs));
+ write_l (2*n_stubs);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+# else
+ int data_section_length;
+
+ data_section_length=data_buffer_offset+4*t_label_number;
+
+ write_w (0x01df);
+ write_w (2);
+ write_l (0);
+ write_l (100+code_buffer_offset+data_section_length+(n_code_relocations+n_data_relocations+t_label_number)*10);
+ write_l ((n_object_labels+1+t_label_number)<<1);
+ write_w (0);
+ write_w (0);
+
+ write_c ('.');
+ write_c ('t');
+ write_c ('e');
+ write_c ('x');
+ write_c ('t');
+ write_c (0);
+ write_c (0);
+ write_c (0);
+
+ write_l (0);
+ write_l (0);
+ write_l (code_buffer_offset);
+ write_l (100);
+ write_l (100+code_buffer_offset+data_section_length);
+ write_l (0);
+ write_w (n_code_relocations);
+ write_w (0);
+ write_l (0x20);
+
+ write_c ('.');
+ write_c ('d');
+ write_c ('a');
+ write_c ('t');
+ write_c ('a');
+ write_c (0);
+ write_c (0);
+ write_c (0);
+
+ write_l (0);
+ write_l (0);
+ write_l (data_section_length);
+ write_l (100+code_buffer_offset);
+ write_l (100+code_buffer_offset+data_section_length+n_code_relocations*10);
+ write_l (0);
+ write_w (n_data_relocations+t_label_number);
+ write_w (0);
+ write_l (0x40);
+# endif
+#endif
+}
+
+#ifdef XCOFF
+static void write_toc (struct toc_label *toc_labels)
+{
+ struct toc_label *toc_label;
+
+ for_l (toc_label,toc_labels,toc_next){
+ struct label *label;
+
+ label=toc_label->toc_label_label;
+
+ if (label->label_object_label==NULL)
+ internal_error_in_function ("write_toc");
+
+ write_l (toc_label->toc_label_offset+label->label_offset);
+ }
+}
+#endif
+
+static void store_references (void)
+{
+ struct relocation *relocation,**relocation_p;
+
+ for (relocation_p=&first_code_relocation; (relocation=*relocation_p)!=NULL; relocation_p=&relocation->next){
+ struct label *label;
+ struct object_label *object_label;
+
+ switch (relocation->kind){
+ case CONDITIONAL_BRANCH_RELOCATION:
+ case DUMMY_CONDITIONAL_BRANCH_RELOCATION:
+ case BRANCH_RELOCATION:
+#ifndef XCOFF
+ case HIGH_RELOCATION:
+ case LOW_RELOCATION:
+ case LONG_WORD_RELOCATION:
+#endif
+ label=relocation->relocation_label;
+ object_label=label->label_object_label;
+ break;
+#ifdef XCOFF
+ case TOC_RELOCATION:
+ case TRL_RELOCATION:
+ label=relocation->relocation_toc_label->toc_label_label;
+ object_label=label->label_object_label;
+ break;
+#endif
+ default:
+ internal_error_in_function ("store_references");
+ }
+
+ if (object_label==NULL)
+ internal_error_in_function ("store_references");
+
+ if (object_label->kind==CODE_CONTROL_SECTION){
+ int label_reference,relocation_label_n,label_n;
+
+ label_n=object_label->object_label_number;
+ relocation_label_n=relocation->relocation_object_label->object_label_number;
+
+ label_reference=object_label->object_label_reference;
+
+ if (relocation_label_n!=label_n){
+ if (label_reference==-1)
+ object_label->object_label_reference=relocation_label_n;
+ else if (label_reference!=relocation_label_n)
+ object_label->object_label_reference=-2;
+ }
+ }
+ }
+
+ for_l (relocation,first_data_relocation,next){
+ struct label *label;
+ struct object_label *object_label;
+
+ label=relocation->relocation_label;
+ object_label=label->label_object_label;
+
+ if (object_label==NULL)
+ internal_error_in_function ("store_references");
+
+ if (relocation->kind==LONG_WORD_RELOCATION && label->label_offset!=0 && object_label->kind==CODE_CONTROL_SECTION)
+ label->label_object_label->object_label_reference=-2;
+ }
+}
+
+static void renumber_object_labels_and_calculate_section_sizes (void)
+{
+ struct object_label *object_label,*previous_code_object_label,*previous_data_object_label;
+#if defined (ELF) || defined (G_MACH_O)
+ int section_object_label_n;
+#endif
+
+ previous_code_object_label=NULL;
+
+ for_l (object_label,first_object_label,next){
+ if (object_label->kind==CODE_CONTROL_SECTION){
+ if (previous_code_object_label!=NULL){
+ int reference1,reference2;
+
+ reference1=previous_code_object_label->object_label_reference;
+ reference2=object_label->object_label_reference;
+
+ if (reference2!=-2){
+ if ( reference2==previous_code_object_label->object_label_number
+ || reference1==object_label->object_label_number
+ || (reference1>=0 && reference2>=0 && reference1==reference2)
+ ){
+ object_label->kind=MERGED_CODE_CONTROL_SECTION;
+ }
+ }
+ }
+
+ previous_code_object_label=object_label;
+ }
+ }
+
+#ifdef ELF
+ section_object_label_n=n_object_labels;
+ n_object_labels=3;
+#else
+# ifdef G_MACH_O
+ section_object_label_n=n_object_labels;
+# endif
+ n_object_labels=0;
+#endif
+
+ previous_data_object_label=NULL;
+ previous_code_object_label=NULL;
+
+ for_l (object_label,first_object_label,next){
+ switch (object_label->kind){
+ case CODE_CONTROL_SECTION:
+#ifndef XCOFF
+ object_label->object_label_number=section_object_label_n;
+ ++section_object_label_n;
+#else
+ object_label->object_label_number=n_object_labels;
+ ++n_object_labels;
+#endif
+ if (previous_code_object_label!=NULL)
+ previous_code_object_label->object_label_size=object_label->object_label_offset-previous_code_object_label->object_label_offset;
+ previous_code_object_label=object_label;
+ break;
+ case DATA_CONTROL_SECTION:
+#ifndef XCOFF
+ object_label->object_label_number=section_object_label_n;
+ ++section_object_label_n;
+#else
+ object_label->object_label_number=n_object_labels;
+ ++n_object_labels;
+#endif
+ if (previous_data_object_label!=NULL)
+ previous_data_object_label->object_label_size=object_label->object_label_offset-previous_data_object_label->object_label_offset;
+ previous_data_object_label=object_label;
+ break;
+ case IMPORTED_CODE_LABEL:
+#ifdef G_MACH_O
+ break;
+#endif
+ case EXPORTED_CODE_LABEL:
+ case EXPORTED_DATA_LABEL:
+ object_label->object_label_number=n_object_labels;
+ ++n_object_labels;
+ break;
+ case MERGED_CODE_CONTROL_SECTION:
+ object_label->object_label_number=previous_code_object_label->object_label_number;
+ break;
+ default:
+ internal_error_in_function ("renumber_object_labels_and_calculate_section_sizes");
+ }
+ }
+
+#ifdef G_MACH_O
+ n_exported_object_labels=n_object_labels;
+
+ for_l (object_label,first_object_label,next)
+ if (object_label->kind==IMPORTED_CODE_LABEL){
+ object_label->object_label_number=n_object_labels;
+ ++n_object_labels;
+ }
+#endif
+
+ if (previous_code_object_label!=NULL)
+ previous_code_object_label->object_label_size=code_buffer_offset-previous_code_object_label->object_label_offset;
+
+ if (previous_data_object_label!=NULL)
+ previous_data_object_label->object_label_size=data_buffer_offset-previous_data_object_label->object_label_offset;
+}
+
+#define R_POS 0
+#define R_TOC 3
+#define R_TRL 0x12 /* 4 */
+#define R_BR 10
+#define R_REF 15
+
+#ifdef ELF
+static void write_relocation_label_number_and_addend (struct label *label,int relocation_type,long addend)
+{
+ struct object_label *object_label;
+
+ object_label=label->label_object_label;
+
+ if (object_label->kind==IMPORTED_CODE_LABEL)
+ write_l (ELF32_R_INFO (object_label->object_label_number,relocation_type));
+ else if (object_label==code_csect_object_label){
+ write_l (ELF32_R_INFO (1,relocation_type));
+ addend+=label->label_offset;
+ } else if (object_label==data_csect_object_label){
+ write_l (ELF32_R_INFO (2,relocation_type));
+ addend+=label->label_offset;
+ } else
+ internal_error_in_function ("write_relocation_label_number_and_addend");
+
+ write_l (addend);
+}
+#endif
+
+#ifdef G_MACH_O
+static void write_relocation_symbol_number_and_kind (struct label *label,int relocation_type)
+{
+ struct object_label *object_label;
+ int label_or_section_number;
+
+ object_label=label->label_object_label;
+
+ if (object_label->kind==IMPORTED_CODE_LABEL){
+ label_or_section_number=object_label->object_label_number;
+ relocation_type |= 1<<4;
+ } else if (object_label==code_csect_object_label)
+ label_or_section_number=1;
+ else if (object_label==data_csect_object_label)
+ label_or_section_number=2;
+ else if (object_label==stub_csect_object_label)
+ label_or_section_number=3;
+ else
+ internal_error_in_function ("write_relocation_symbol_number_and_kind");
+
+ fputc (label_or_section_number>>16,output_file);
+ fputc (label_or_section_number>>8,output_file);
+ fputc (label_or_section_number,output_file);
+ fputc (relocation_type,output_file);
+}
+#endif
+
+static void write_code_relocations (void)
+{
+ struct relocation *relocation;
+
+#if 1 && defined (G_MACH_O)
+ {
+ struct relocation *previous_relocation,*next_relocation;
+
+ relocation=first_code_relocation;
+ previous_relocation=NULL;
+ while (relocation!=NULL){
+ next_relocation=relocation->next;
+ relocation->next=previous_relocation;
+ previous_relocation=relocation;
+ relocation=next_relocation;
+ }
+ first_code_relocation=previous_relocation;
+ }
+#endif
+
+ for_l (relocation,first_code_relocation,next){
+ switch (relocation->kind){
+ case CONDITIONAL_BRANCH_RELOCATION:
+ {
+ struct label *label;
+
+ label=relocation->relocation_label;
+ if (label->label_object_label==NULL)
+ internal_error_in_function ("write_code_relocations");
+
+ write_l (relocation->offset+2);
+#ifdef ELF
+ write_relocation_label_number_and_addend (label,R_PPC_REL14,0);
+#elif defined (G_MACH_O)
+ write_relocation_symbol_number_and_kind (label,PPC_RELOC_BR14 | (2<<5) | (1<<7));
+#else
+ write_l (label->label_object_label->object_label_number<<1);
+ write_c (0x80+16-1);
+ write_c (R_BR);
+#endif
+ break;
+ }
+ case DUMMY_CONDITIONAL_BRANCH_RELOCATION:
+ {
+ struct label *label;
+
+ label=relocation->relocation_label;
+ if (label->label_object_label==NULL)
+ internal_error_in_function ("write_code_relocations");
+
+ write_l (relocation->offset+2);
+#ifdef ELF
+ write_relocation_label_number_and_addend (label,R_PPC_REL14,0);
+#else
+ write_l (label->label_object_label->object_label_number<<1);
+ write_c (0x80+16-1);
+ write_c (R_REF /* R_BR */);
+#endif
+ break;
+ }
+ case BRANCH_RELOCATION:
+ {
+ struct label *label;
+
+ label=relocation->relocation_label;
+ if (label->label_object_label==NULL)
+ internal_error_in_function ("write_code_relocations");
+
+ write_l (relocation->offset);
+#ifdef ELF
+ write_relocation_label_number_and_addend (label,R_PPC_REL24,0);
+#elif defined (G_MACH_O)
+ write_relocation_symbol_number_and_kind (label,PPC_RELOC_BR24 | (2<<5) | (1<<7));
+#else
+ write_l (label->label_object_label->object_label_number<<1);
+ write_c (0x80+26-1);
+ write_c (R_BR);
+#endif
+ break;
+ }
+#ifdef XCOFF
+ case TOC_RELOCATION:
+ write_l (relocation->offset+2);
+ write_l ((relocation->relocation_toc_label->toc_t_label_number+n_object_labels+1)<<1);
+ write_c (16-1);
+ write_c (R_TOC);
+ break;
+ case TRL_RELOCATION:
+ write_l (relocation->offset+2);
+ write_l ((relocation->relocation_toc_label->toc_t_label_number+n_object_labels+1)<<1);
+ write_c (16-1);
+# ifdef TRL_RELOCATIONS
+ write_c (R_TRL);
+# else
+ write_c (R_TOC);
+# endif
+ break;
+#else
+ case HIGH_RELOCATION:
+ {
+# ifdef G_MACH_O
+ int addend;
+ struct label *label;
+
+ write_l (relocation->offset);
+ write_relocation_symbol_number_and_kind (relocation->relocation_label,PPC_RELOC_HA16 | (2<<5));
+
+ label=relocation->relocation_label;
+ if (label->label_object_label==NULL)
+ internal_error_in_function ("write_code_relocations");
+
+ addend=relocation->relocation_addend+relocation->relocation_label->label_offset;
+ if (label->label_object_label->kind==DATA_CONTROL_SECTION || label->label_object_label->kind==EXPORTED_DATA_LABEL)
+ addend+=code_buffer_offset;
+
+ write_l (((unsigned)addend) & 0xffff);
+ write_l (PPC_RELOC_PAIR | (2<<5));
+# else
+ write_l (relocation->offset+2);
+ write_relocation_label_number_and_addend (relocation->relocation_label,R_PPC_ADDR16_HA,
+ relocation->relocation_addend);
+# endif
+ break;
+ }
+ case LOW_RELOCATION:
+ {
+# ifdef G_MACH_O
+ int addend;
+ struct label *label;
+
+ label=relocation->relocation_label;
+ if (label->label_object_label==NULL)
+ internal_error_in_function ("write_code_relocations");
+
+ write_l (relocation->offset);
+ write_relocation_symbol_number_and_kind (relocation->relocation_label,PPC_RELOC_LO16 | (2<<5));
+
+ addend=relocation->relocation_addend+relocation->relocation_label->label_offset;
+ if (label->label_object_label->kind==DATA_CONTROL_SECTION || label->label_object_label->kind==EXPORTED_DATA_LABEL)
+ addend+=code_buffer_offset;
+
+ write_l (((unsigned)addend)>>16);
+ write_l (PPC_RELOC_PAIR | (2<<5));
+# else
+ write_l (relocation->offset+2);
+ write_relocation_label_number_and_addend (relocation->relocation_label,R_PPC_ADDR16_LO,
+ relocation->relocation_addend);
+# endif
+ break;
+ }
+ case LONG_WORD_RELOCATION:
+ write_l (relocation->offset);
+# ifdef G_MACH_O
+ write_relocation_symbol_number_and_kind (relocation->relocation_label,PPC_RELOC_VANILLA | (2<<5));
+# else
+ write_relocation_label_number_and_addend (relocation->relocation_label,R_PPC_ADDR32,
+ relocation->relocation_addend);
+# endif
+ break;
+#endif
+ default:
+ internal_error_in_function ("write_code_relocations");
+ }
+ }
+}
+
+static void write_data_relocations (void)
+{
+ struct relocation *relocation;
+
+#if 1 && defined (G_MACH_O)
+ {
+ struct relocation *previous_relocation,*next_relocation;
+
+ relocation=first_data_relocation;
+ previous_relocation=NULL;
+ while (relocation!=NULL){
+ next_relocation=relocation->next;
+ relocation->next=previous_relocation;
+ previous_relocation=relocation;
+ relocation=next_relocation;
+ }
+ first_data_relocation=previous_relocation;
+ }
+#endif
+
+ for_l (relocation,first_data_relocation,next){
+ struct label *label;
+
+ label=relocation->relocation_label;
+
+ if (label->label_object_label==NULL)
+ internal_error_in_function ("write_data_relocations");
+
+ switch (relocation->kind){
+ case LONG_WORD_RELOCATION:
+ write_l (relocation->offset);
+#ifdef ELF
+ write_relocation_label_number_and_addend (label,R_PPC_ADDR32,relocation->relocation_addend);
+#elif defined (G_MACH_O)
+ write_relocation_symbol_number_and_kind (label,PPC_RELOC_VANILLA | (2<<5));
+#else
+ write_l (label->label_object_label->object_label_number<<1);
+ write_c (32-1);
+ write_c (R_POS);
+#endif
+ break;
+ default:
+ internal_error_in_function ("write_data_relocations");
+ }
+ }
+}
+
+#ifdef XCOFF
+static void write_toc_relocations (struct toc_label *toc_labels)
+{
+ struct toc_label *toc_label;
+
+ for_l (toc_label,toc_labels,toc_next){
+ struct label *label;
+
+ label=toc_label->toc_label_label;
+
+ if (label->label_object_label==NULL)
+ internal_error_in_function ("write_toc_label_relocations");
+
+ write_l (data_buffer_offset+(toc_label->toc_t_label_number<<2));
+ write_l (label->label_object_label->object_label_number<<1);
+ write_c (32-1);
+ write_c (R_POS);
+ }
+}
+#endif
+
+#define C_EXT 2
+#define C_HIDEXT 107
+
+#define XTY_ER 0
+#define XTY_SD 1
+#define XTY_LD 2
+
+#define XMC_PR 0
+#define XMC_TC 3
+#define XMC_RW 5
+#define XMC_DS 10
+#define XMC_TC0 15
+
+static void write_string_8 (char *string)
+{
+ int i;
+
+ i=0;
+
+ while (i<8){
+ char c;
+
+ c=string[i++];
+ write_c (c);
+
+ if (c=='\0'){
+ while (i<8){
+ write_c ('\0');
+ ++i;
+ }
+ return;
+ }
+ }
+}
+
+static void write_object_labels (void)
+{
+ struct object_label *object_label;
+ int code_section_number,data_section_number;
+
+ code_section_number=0;
+ data_section_number=0;
+
+#ifdef ELF
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+
+ write_l (1);
+ write_l (0);
+ write_l (0);
+ write_c (ELF32_ST_INFO (STB_LOCAL,STT_SECTION));
+ write_c (0);
+ write_w (2);
+
+ write_l (7);
+ write_l (0);
+ write_l (0);
+ write_c (ELF32_ST_INFO (STB_LOCAL,STT_SECTION));
+ write_c (0);
+ write_w (3);
+#endif
+
+ for_l (object_label,first_object_label,next){
+ switch (object_label->kind){
+ case CODE_CONTROL_SECTION:
+ {
+#if !(defined (ELF) || defined (G_MACH_O))
+ char section_name[16];
+
+ sprintf (section_name,".m_%d",code_section_number);
+ ++code_section_number;
+ write_string_8 (section_name);
+
+ write_l (object_label->object_label_offset);
+ write_w (1);
+ write_w (0);
+ write_c (C_HIDEXT);
+ write_c (1);
+
+ write_l (object_label->object_label_size);
+ write_l (0);
+ write_w (0);
+ write_c ((2<<3)|XTY_SD);
+ write_c (XMC_PR);
+ write_l (0);
+ write_w (0);
+#endif
+ break;
+ }
+ case DATA_CONTROL_SECTION:
+ {
+#if !(defined (ELF) || defined (G_MACH_O))
+ char section_name[16];
+
+ sprintf (section_name,".d_%d",data_section_number);
+ ++data_section_number;
+ write_string_8 (section_name);
+
+ write_l (object_label->object_label_offset);
+ write_w (2);
+ write_w (0);
+ write_c (C_HIDEXT);
+ write_c (1);
+
+ write_l (object_label->object_label_size);
+ write_l (0);
+ write_w (0);
+ write_c ((2<<3)|XTY_SD);
+ write_c (XMC_RW);
+ write_l (0);
+ write_w (0);
+#endif
+ break;
+ }
+ case IMPORTED_CODE_LABEL:
+ {
+ struct label *label;
+
+ label=object_label->object_label_label;
+#ifdef ELF
+ write_l (object_label->object_label_string_offset);
+ write_l (0);
+ write_l (0);
+ write_c (ELF32_ST_INFO (STB_GLOBAL,STT_NOTYPE));
+ write_c (0);
+ write_w (0);
+#else
+# ifdef G_MACH_O
+# else
+ if (object_label->object_label_string_offset==0)
+ write_string_8 (label->label_name);
+ else {
+ write_l (0);
+ write_l (object_label->object_label_string_offset);
+ }
+
+ write_l (0);
+ write_w (0);
+ write_w (0);
+ write_c (C_EXT);
+ write_c (1);
+
+ write_l (0);
+ write_l (0);
+ write_w (0);
+ write_c ((2<<3)|XTY_ER);
+ write_c (XMC_PR);
+ write_l (0);
+ write_w (0);
+# endif
+#endif
+ break;
+ }
+ case EXPORTED_CODE_LABEL:
+ {
+ struct label *label;
+
+ label=object_label->object_label_label;
+#ifdef ELF
+ write_l (object_label->object_label_string_offset);
+ write_l (label->label_offset);
+ write_l (0);
+ write_c (ELF32_ST_INFO (STB_GLOBAL,STT_FUNC));
+ write_c (0);
+ write_w (2);
+#else
+# ifdef G_MACH_O
+ write_l (object_label->object_label_string_offset);
+ write_c (N_SECT | N_EXT);
+ write_c (1);
+ write_w (0);
+ write_l (label->label_offset);
+# else
+ if (object_label->object_label_string_offset==0)
+ write_string_8 (label->label_name);
+ else {
+ write_l (0);
+ write_l (object_label->object_label_string_offset);
+ }
+
+ write_l (label->label_offset);
+ write_w (1);
+ write_w (0);
+ write_c (C_EXT);
+ write_c (1);
+
+ write_l (label->label_object_label->object_label_number<<1);
+ write_l (0);
+ write_w (0);
+ write_c ((2<<3)|XTY_LD);
+ write_c (XMC_PR);
+ write_l (0);
+ write_w (0);
+# endif
+#endif
+ break;
+ }
+ case EXPORTED_DATA_LABEL:
+ {
+ struct label *label;
+
+ label=object_label->object_label_label;
+#ifdef ELF
+ write_l (object_label->object_label_string_offset);
+ write_l (label->label_offset);
+ write_l (0);
+ write_c (ELF32_ST_INFO (STB_GLOBAL,STT_OBJECT));
+ write_c (0);
+ write_w (3);
+#else
+# ifdef G_MACH_O
+ write_l (object_label->object_label_string_offset);
+ write_c (N_SECT | N_EXT);
+ write_c (2);
+ write_w (0);
+ write_l (label->label_offset + code_buffer_offset);
+# else
+ if (object_label->object_label_string_offset==0)
+ write_string_8 (label->label_name);
+ else {
+ write_l (0);
+ write_l (object_label->object_label_string_offset);
+ }
+
+ write_l (label->label_offset);
+ write_w (2);
+ write_w (0);
+ write_c (C_EXT);
+ write_c (1);
+
+ write_l (label->label_object_label->object_label_number<<1);
+ write_l (0);
+ write_w (0);
+ write_c ((2<<3)|XTY_LD);
+ write_c (XMC_RW);
+ write_l (0);
+ write_w (0);
+# endif
+#endif
+ break;
+ }
+ case MERGED_CODE_CONTROL_SECTION:
+ break;
+ default:
+ internal_error_in_function ("write_object_labels");
+ }
+ }
+
+#ifdef G_MACH_O
+ for_l (object_label,first_object_label,next)
+ if (object_label->kind==IMPORTED_CODE_LABEL){
+ struct label *label;
+
+ label=object_label->object_label_label;
+
+ write_l (object_label->object_label_string_offset);
+ write_c (N_UNDF | N_EXT);
+ write_c (NO_SECT);
+ write_w (0);
+ write_l (0);
+ }
+#endif
+}
+
+#ifdef XCOFF
+static void write_toc_labels (struct toc_label *toc_labels)
+{
+ struct toc_label *toc_label;
+ int toc_offset;
+
+ toc_offset=data_buffer_offset;
+
+ write_c ('T');
+ write_c ('O');
+ write_c ('C');
+ write_c ('\0');
+ write_c ('\0');
+ write_c ('\0');
+ write_c ('\0');
+ write_c ('\0');
+
+ write_l (toc_offset);
+ write_w (2);
+ write_w (0);
+ write_c (C_HIDEXT);
+ write_c (1);
+
+ write_l (0);
+ write_l (0);
+ write_w (0);
+ write_c ((2<<3)|XTY_SD);
+ write_c (XMC_TC0);
+ write_l (0);
+ write_w (0);
+
+ for_l (toc_label,toc_labels,toc_next){
+ char toc_entry_name[16];
+
+ sprintf (toc_entry_name,"t_%d",toc_label->toc_t_label_number);
+
+ write_string_8 (toc_entry_name);
+
+ write_l (toc_offset);
+ write_w (2);
+ write_w (0);
+ write_c (C_HIDEXT);
+ write_c (1);
+
+ write_l (4);
+ write_l (0);
+ write_w (0);
+ write_c ((2<<3)|XTY_SD);
+ write_c (XMC_TC);
+ write_l (0);
+ write_w (0);
+
+ toc_offset+=4;
+ }
+}
+#endif
+
+static void write_string_table (void)
+{
+ struct object_label *object_label;
+
+#ifdef ELF
+ write_c (0);
+ write_zstring (".text");
+ write_zstring (".data");
+#else
+ if (string_table_offset==4)
+ return;
+
+ write_l (string_table_offset);
+#endif
+ for_l (object_label,first_object_label,next){
+ int object_label_kind;
+
+ object_label_kind=object_label->kind;
+
+ if ((object_label_kind==IMPORTED_CODE_LABEL || object_label_kind==EXPORTED_CODE_LABEL || object_label_kind==EXPORTED_DATA_LABEL)
+ && object_label->object_label_string_offset!=0)
+ {
+ char *s,c;
+
+ s=object_label->object_label_label->label_name;
+
+ do {
+ c=*s++;
+ write_c (c);
+ } while (c!='\0');
+ }
+ }
+}
+
+#ifdef DYNAMIC_CODEGENERATOR
+extern void allocate_memory_for_object_file (int object_file_size);
+#endif
+
+void assemble_code (void)
+{
+ as_import_labels (labels);
+
+ write_code();
+
+ flush_data_buffer();
+ flush_code_buffer();
+ *last_toc_next_p=NULL;
+
+#ifdef G_MACH_O
+ compute_offsets_of_stub_labels();
+#endif
+ store_references();
+ renumber_object_labels_and_calculate_section_sizes();
+
+ relocate_branches();
+ relocate_data();
+
+#ifdef DYNAMIC_CODEGENERATOR
+ allocate_memory_for_object_file (100+code_buffer_offset+data_buffer_offset+4*t_label_number
+ +(n_code_relocations+n_data_relocations+t_label_number)*10
+ +((n_object_labels+1+t_label_number)<<1)*18+string_table_offset);
+#endif
+
+ write_file_header_and_section_headers();
+
+ write_buffers_and_release_memory (&first_code_buffer);
+ write_buffers_and_release_memory (&first_data_buffer);
+#ifdef XCOFF
+ write_toc (toc_labels);
+#endif
+#ifdef G_MACH_O
+ write_stubs();
+#endif
+
+ write_code_relocations();
+ write_data_relocations();
+#ifdef XCOFF
+ write_toc_relocations (toc_labels);
+#endif
+#ifdef G_MACH_O
+ write_stub_relocations_and_indirect_symbols();
+#endif
+
+ write_object_labels();
+#ifdef XCOFF
+ write_toc_labels (toc_labels);
+#endif
+ write_string_table();
+}
+
+#endif
diff --git a/cgpwas.c b/cgpwas.c
new file mode 100644
index 0000000..23f7add
--- /dev/null
+++ b/cgpwas.c
@@ -0,0 +1,3421 @@
+/*
+ File: cgpwas.c
+ Machine: Power Macintosh
+ Author: John van Groningen
+ Copyright: University of Nijmegen
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "cgport.h"
+
+#ifdef MACH_O
+#define GNU_SYNTAX
+#endif
+#undef ONLY_REGISTER_NUMBERS
+
+#ifdef GNU_SYNTAX
+# define IF_GNU(a,b) a
+#else
+# define IF_GNU(a,b) b
+#endif
+
+#ifdef MACH_O
+# define IF_MACH_O(a,b) a
+#else
+# define IF_MACH_O(a,b) b
+#endif
+
+#ifndef MACH_O
+# define NEWLINE_STRING "\015"
+# define NEWLINE_CHAR '\015'
+#else
+# define NEWLINE_STRING "\012"
+# define NEWLINE_CHAR '\012'
+#endif
+
+#ifdef G_POWER
+
+#include "cgrconst.h"
+#include "cgtypes.h"
+#include "cg.h"
+#include "cgiconst.h"
+#include "cgcode.h"
+#include "cginstructions.h"
+#include "cgptoc.h"
+#include "cgpwas.h"
+
+#define for_l(v,l,n) for(v=(l);v!=NULL;v=v->n)
+
+#define FSUB_FDIV_REVERSED
+
+#define IO_BUF_SIZE 8192
+
+static FILE *assembly_file;
+
+static void w_as_newline (VOID)
+{
+ putc (NEWLINE_CHAR,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" NEWLINE_STRING,opcode);
+}
+
+static void w_as_define_local_label (int label_number)
+{
+ fprintf (assembly_file,"l_%d:" NEWLINE_STRING,label_number);
+}
+
+static void w_as_define_internal_label (int label_number)
+{
+ fprintf (assembly_file,"i_%d:" NEWLINE_STRING,label_number);
+}
+
+#define DC_L IF_GNU (".long","dc.l")
+#define DC_B IF_GNU (".byte","dc.b")
+
+void w_as_internal_label_value (int label_id)
+{
+ fprintf (assembly_file,"\t" DC_L "\ti_%d" NEWLINE_STRING,label_id);
+}
+
+static int in_data_section;
+
+static int data_module_number,code_module_number;
+
+static void w_as_new_code_module (VOID)
+{
+ ++code_module_number;
+#ifdef GNU_SYNTAX
+ fprintf (assembly_file,IF_MACH_O ("\t.text" NEWLINE_STRING,"\t.section\t\".text\"" NEWLINE_STRING));
+#else
+ fprintf (assembly_file,"\tcsect\t.m_%d{PR}" NEWLINE_STRING,code_module_number);
+#endif
+ in_data_section=0;
+}
+
+static void w_as_to_code_section (VOID)
+{
+ if (in_data_section){
+ in_data_section=0;
+#ifdef GNU_SYNTAX
+ fprintf (assembly_file,IF_MACH_O ("\t.text" NEWLINE_STRING,"\t.section\t\".text\"" NEWLINE_STRING));
+#else
+ fprintf (assembly_file,"\tcsect\t.m_%d{PR}" NEWLINE_STRING,code_module_number);
+#endif
+ }
+}
+
+void w_as_new_data_module (VOID)
+{
+ ++data_module_number;
+#ifdef GNU_SYNTAX
+ fprintf (assembly_file,IF_MACH_O ("\t.data" NEWLINE_STRING,"\t.section\t\".data\"" NEWLINE_STRING));
+#else
+ fprintf (assembly_file,"\tcsect\t.d_%d{RW}" NEWLINE_STRING,data_module_number);
+#endif
+ in_data_section=1;
+}
+
+void w_as_to_data_section (VOID)
+{
+ if (!in_data_section){
+ in_data_section=1;
+#ifdef GNU_SYNTAX
+ fprintf (assembly_file,IF_MACH_O ("\t.data" NEWLINE_STRING,"\t.section\t\".data\"" NEWLINE_STRING));
+#else
+ fprintf (assembly_file,"\tcsect\t.d_%d{RW}" NEWLINE_STRING,data_module_number);
+#endif
+ }
+}
+
+void w_as_word_in_data_section (int n)
+{
+ w_as_to_data_section();
+ w_as_opcode (IF_GNU (IF_MACH_O (".short",".word"),"dc.w"));
+ fprintf (assembly_file,"%d",n);
+ w_as_newline();
+}
+
+void w_as_long_in_data_section (int n)
+{
+ w_as_to_data_section();
+ w_as_opcode (DC_L);
+ 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" DC_L "\t%s" NEWLINE_STRING,label_name);
+}
+
+static void w_as_label_in_code_section (char *label_name)
+{
+ w_as_to_code_section ();
+ fprintf (assembly_file,"\t" DC_L "\t%s" NEWLINE_STRING,label_name);
+}
+
+void w_as_descriptor_in_data_section (char *label_name)
+{
+ w_as_to_data_section ();
+ fprintf (assembly_file,"\t" DC_L "\t%s+2" NEWLINE_STRING,label_name);
+}
+
+#define MAX_BYTES_PER_LINE 16
+
+static int w_as_data (int n,char *data_p,int length)
+{
+ int i,in_string;
+ unsigned char *data;
+
+ data=(unsigned char*)data_p;
+
+ in_string=0;
+
+ for (i=0; i<length; ++i){
+ int c;
+
+ if (n>=MAX_BYTES_PER_LINE){
+ if (in_string){
+ putc (IF_GNU ('\"','\''),assembly_file);
+ in_string=0;
+ }
+ w_as_newline();
+ n=0;
+ }
+
+ c=data[i];
+ if (isalnum (c) || c=='_' || c==' '){
+ if (!in_string){
+ if (n!=0)
+ w_as_newline();
+ w_as_opcode (IF_MACH_O (".ascii",DC_B));
+ putc (IF_GNU ('\"','\''),assembly_file);
+ in_string=1;
+ }
+ putc (c,assembly_file);
+ } else {
+ if (n==0)
+ w_as_opcode (DC_B);
+ else {
+ if (in_string){
+ putc (IF_GNU ('\"','\''),assembly_file);
+ w_as_newline();
+ w_as_opcode (DC_B);
+ in_string=0;
+ } else
+ putc (',',assembly_file);
+ }
+
+ fprintf (assembly_file,"0x%02x",c);
+ }
+ ++n;
+ }
+
+ if (in_string){
+ putc (IF_GNU ('\"','\''),assembly_file);
+ w_as_newline();
+ return 0;
+ } else
+ return n;
+}
+
+static int w_as_zeros (int n,int length)
+{
+ 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 (DC_B);
+ else
+ putc (',',assembly_file);
+ fprintf (assembly_file,"0");
+ ++n;
+ }
+ return n;
+}
+
+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));
+ else
+ n=w_as_zeros (n,4);
+ w_as_newline();
+}
+
+void w_as_define_data_label (int label_number)
+{
+ w_as_to_data_section();
+
+ w_as_define_local_label (label_number);
+}
+
+void w_as_abc_string_in_data_section (char *string,int length)
+{
+ int n;
+
+ w_as_to_data_section();
+
+ w_as_opcode (DC_L);
+ fprintf (assembly_file,"%d" NEWLINE_STRING,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_labeled_c_string_in_data_section (char *string,int length,int label_number)
+{
+ int n;
+
+ w_as_to_data_section();
+
+ w_as_define_local_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_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_label (string_label_id);
+ w_as_define_local_label (string_label->label_number);
+
+ w_as_opcode (DC_L);
+ fprintf (assembly_file,"%d" NEWLINE_STRING,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_opcode_and_d (char *opcode)
+{
+ fprintf (assembly_file,"\t%sd\t",opcode);
+}
+
+static void w_as_label (char *label)
+{
+ int c;
+
+ while (c=*label++,c!=0)
+ putc (c,assembly_file);
+}
+
+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();
+}
+
+void w_as_define_label (LABEL *label)
+{
+ if (label->label_flags & EXPORT_LABEL){
+ w_as_opcode (IF_GNU (IF_MACH_O (".globl",".global"),"export"));
+ 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_local_label (int label_number)
+{
+ fprintf (assembly_file,"l_%d",label_number);
+}
+
+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_label_name (label_name);
+
+ w_as_opcode (DC_L);
+ fprintf (assembly_file,"%d" NEWLINE_STRING,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();
+}
+
+#define REGISTER_O0 (-13)
+#define REGISTER_O1 (-23)
+#define REGISTER_R0 (-24)
+#define REGISTER_R3 (-21)
+#define REGISTER_SP (-12)
+
+static unsigned char real_reg_num [32] =
+{
+ 0,12,2,3,4,5,6,7,8,9,10,11,1,13,14,15,
+ 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+};
+
+#define reg_num(r) (real_reg_num[(r)+24])
+
+static void w_as_indirect (int i,int reg)
+{
+#ifdef ONLY_REGISTER_NUMBERS
+ if (i>=0)
+ fprintf (assembly_file,"%d(%d)",i,reg_num (reg));
+ else
+ fprintf (assembly_file,"-%d(%d)",-i,reg_num (reg));
+#else
+ if (i>=0)
+ fprintf (assembly_file,"%d(r%d)",i,reg_num (reg));
+ else
+ fprintf (assembly_file,"-%d(r%d)",-i,reg_num (reg));
+#endif
+}
+
+static void w_as_indexed (int offset,struct index_registers *index_registers)
+{
+ int reg1,reg2;
+
+ if (offset!=0)
+ internal_error_in_function ("w_as_indexed");
+
+ reg1=index_registers->a_reg.r;
+ reg2=index_registers->d_reg.r;
+#ifdef ONLY_REGISTER_NUMBERS
+ fprintf (assembly_file,"%d,%d",reg_num (reg1),reg_num (reg2));
+#else
+ fprintf (assembly_file,"r%d,r%d",reg_num (reg1),reg_num (reg2));
+#endif
+}
+
+static void w_as_register (int reg)
+{
+#ifdef ONLY_REGISTER_NUMBERS
+ fprintf (assembly_file,"%d",reg_num (reg));
+#else
+ fprintf (assembly_file,"r%d",reg_num (reg));
+#endif
+}
+
+static void w_as_register_comma (int reg)
+{
+#ifdef ONLY_REGISTER_NUMBERS
+ fprintf (assembly_file,"%d,",reg_num (reg));
+#else
+ fprintf (assembly_file,"r%d,",reg_num (reg));
+#endif
+}
+
+static void w_as_register_newline (int reg)
+{
+#ifdef ONLY_REGISTER_NUMBERS
+ fprintf (assembly_file,"%d" NEWLINE_STRING,reg_num (reg));
+#else
+ fprintf (assembly_file,"r%d" NEWLINE_STRING,reg_num (reg));
+#endif
+}
+
+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_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)
+{
+ w_as_register (REGISTER_O0);
+}
+
+static void w_as_fp_register (int fp_reg)
+{
+#ifdef ONLY_REGISTER_NUMBERS
+ fprintf (assembly_file,"%d",fp_reg+14);
+#else
+ fprintf (assembly_file,IF_MACH_O ("f%d","fp%d"),fp_reg+14);
+#endif
+}
+
+static void w_as_comma (VOID)
+{
+ putc (',',assembly_file);
+}
+
+static void w_as_toc_label (struct toc_label *toc_label)
+{
+ struct label *label;
+ int offset,t_label_number;
+
+ offset=toc_label->toc_label_offset;
+ label=toc_label->toc_label_label;
+ t_label_number=toc_label->toc_t_label_number;
+
+ if (offset!=0){
+ w_as_opcode ("tc");
+ fprintf (assembly_file,"t_%d{TC}",t_label_number);
+ w_as_comma();
+ if (label->label_number!=0)
+ w_as_local_label (label->label_number);
+ else
+ w_as_label (label->label_name);
+ if (offset>=0)
+ fprintf (assembly_file,"+%d" NEWLINE_STRING,offset);
+ else
+ fprintf (assembly_file,"-%d" NEWLINE_STRING,-offset);
+ } else {
+ w_as_opcode ("tc");
+ fprintf (assembly_file,"t_%d{TC}",t_label_number);
+ w_as_comma();
+ if (label->label_number!=0)
+ w_as_local_label (label->label_number);
+ else
+ w_as_label (label->label_name);
+ w_as_newline();
+ }
+}
+
+#ifdef GNU_SYNTAX
+static void load_label (struct label *label,int offset,int reg)
+{
+ w_as_opcode ("lis");
+ w_as_register_comma (reg);
+
+# ifdef MACH_O
+ fprintf (assembly_file,"ha16(");
+# endif
+ if (label->label_number!=0)
+ w_as_local_label (label->label_number);
+ else
+ w_as_label (label->label_name);
+ if (offset!=0){
+ if (offset>=0)
+ fprintf (assembly_file,"+%d",offset);
+ else
+ fprintf (assembly_file,"-%d",-offset);
+ }
+# ifdef MACH_O
+ fprintf (assembly_file,")" NEWLINE_STRING);
+# else
+ fprintf (assembly_file,"@ha" NEWLINE_STRING);
+# endif
+
+ w_as_opcode ("addi");
+ w_as_register_comma (reg);
+ w_as_register_comma (reg);
+
+# ifdef MACH_O
+ fprintf (assembly_file,"lo16(");
+# endif
+ if (label->label_number!=0)
+ w_as_local_label (label->label_number);
+ else
+ w_as_label (label->label_name);
+ if (offset!=0){
+ if (offset>=0)
+ fprintf (assembly_file,"+%d",offset);
+ else
+ fprintf (assembly_file,"-%d",-offset);
+ }
+# ifdef MACH_O
+ fprintf (assembly_file,")" NEWLINE_STRING);
+# else
+ fprintf (assembly_file,"@l" NEWLINE_STRING);
+# endif
+}
+#endif
+
+static void w_as_load_descriptor (struct parameter *parameter,int reg)
+{
+#ifdef GNU_SYNTAX
+ load_label (parameter->parameter_data.l,2+(parameter->parameter_offset<<3),reg);
+#else
+ int t_label_number;
+
+ t_label_number=make_toc_label (parameter->parameter_data.l,2+(parameter->parameter_offset<<3));
+
+ w_as_opcode ("lwz");
+ w_as_register_comma (reg);
+ fprintf (assembly_file,"t_%d{TC}(RTOC)" NEWLINE_STRING,t_label_number);
+#endif
+}
+
+static void w_as_load_label_parameter (struct parameter *parameter,int reg)
+{
+#ifdef GNU_SYNTAX
+ load_label (parameter->parameter_data.l,parameter->parameter_offset,reg);
+#else
+ int t_label_number;
+
+ t_label_number=make_toc_label (parameter->parameter_data.l,parameter->parameter_offset);
+
+ w_as_opcode ("lwz");
+ w_as_register_comma (reg);
+ fprintf (assembly_file,"t_%d{TC}(RTOC)" NEWLINE_STRING,t_label_number);
+#endif
+}
+
+static void w_as_load_label (struct label *label,int reg)
+{
+#ifdef GNU_SYNTAX
+ load_label (label,0,reg);
+#else
+ int t_label_number;
+
+ t_label_number=make_toc_label (label,0);
+
+ w_as_opcode ("lwz");
+ w_as_register_comma (reg);
+ fprintf (assembly_file,"t_%d{TC}(RTOC)" NEWLINE_STRING,t_label_number);
+#endif
+}
+
+static void w_as_load_label_with_offset (struct label *label,int offset,int reg)
+{
+#ifdef GNU_SYNTAX
+ load_label (label,offset,reg);
+#else
+ int t_label_number;
+
+ t_label_number=make_toc_label (label,offset);
+
+ w_as_opcode ("lwz");
+ w_as_register_comma (reg);
+ fprintf (assembly_file,"t_%d{TC}(RTOC)" NEWLINE_STRING,t_label_number);
+#endif
+}
+
+static void w_as_parameter (register struct parameter *parameter)
+{
+ switch (parameter->parameter_type){
+ case P_REGISTER:
+ w_as_register (parameter->parameter_data.reg.r);
+ break;
+ 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:
+ w_as_indirect (parameter->parameter_offset,parameter->parameter_data.reg.r);
+ break;
+ case P_INDEXED:
+ w_as_indexed (parameter->parameter_offset,parameter->parameter_data.ir);
+ break;
+ case P_IMMEDIATE:
+ fprintf (assembly_file,"%ld",parameter->parameter_data.i);
+ break;
+ case P_F_REGISTER:
+#ifdef ONLY_REGISTER_NUMBERS
+ fprintf (assembly_file,"%d",parameter->parameter_data.reg.r+14);
+#else
+ fprintf (assembly_file,IF_MACH_O ("f%d","fp%d"),parameter->parameter_data.reg.r+14);
+#endif
+ break;
+ default:
+ internal_error_in_function ("w_as_parameter");
+ }
+}
+
+static int w_as_register_parameter (struct parameter parameter,int size_flag)
+{
+ switch (parameter.parameter_type){
+ case P_DESCRIPTOR_NUMBER:
+ w_as_load_descriptor (&parameter,REGISTER_O0);
+
+ return REGISTER_O0;
+ case P_IMMEDIATE:
+ {
+ int i;
+
+ i=parameter.parameter_data.i;
+
+ if (i!=(WORD)i){
+ w_as_opcode ("lis");
+ w_as_register_comma (REGISTER_O0);
+ w_as_immediate ((i-(WORD)i)>>16);
+ w_as_newline();
+
+ i=(WORD)i;
+
+ w_as_opcode ("addi");
+ w_as_register_comma (REGISTER_O0);
+ w_as_register_comma (REGISTER_O0);
+ w_as_immediate (i);
+ w_as_newline();
+ } else {
+ w_as_opcode ("li");
+ w_as_register_comma (REGISTER_O0);
+ w_as_immediate (i);
+ w_as_newline();
+ }
+
+ return REGISTER_O0;
+ }
+ case P_REGISTER:
+ return parameter.parameter_data.reg.r;
+ case P_INDIRECT:
+ w_as_opcode (size_flag==SIZE_LONG ? "lwz" :
+ size_flag==SIZE_WORD ? "lha" : /* "ldsb" */ "lbz");
+ w_as_register_comma (REGISTER_O0);
+ w_as_indirect (parameter.parameter_offset,parameter.parameter_data.reg.r);
+ w_as_newline();
+
+ return REGISTER_O0;
+ case P_INDIRECT_WITH_UPDATE:
+ w_as_opcode (size_flag==SIZE_LONG ? "lwzu" :
+ size_flag==SIZE_WORD ? "lhau" : /* "ldsb" */ "lbzu");
+ w_as_register_comma (REGISTER_O0);
+ w_as_indirect (parameter.parameter_offset,parameter.parameter_data.reg.r);
+ w_as_newline();
+
+ return REGISTER_O0;
+ case P_INDEXED:
+ w_as_opcode (size_flag==SIZE_LONG ? "lwzx" :
+ size_flag==SIZE_WORD ? "lhax" : /*"ldsbx" */ "lbzx" );
+ w_as_register_comma (REGISTER_O0);
+ w_as_indexed (parameter.parameter_offset,parameter.parameter_data.ir);
+ w_as_newline();
+
+ return REGISTER_O0;
+ default:
+ internal_error_in_function ("w_as_register_parameter");
+ return REGISTER_O0;
+ }
+}
+
+static void w_as_move_instruction (struct instruction *instruction,int size_flag)
+{
+ switch (instruction->instruction_parameters[1].parameter_type){
+ case P_REGISTER:
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_DESCRIPTOR_NUMBER:
+ w_as_load_descriptor (
+ &instruction->instruction_parameters[0],
+ instruction->instruction_parameters[1].parameter_data.reg.r
+ );
+ return;
+ case P_IMMEDIATE:
+ {
+ int i,r;
+
+ i=instruction->instruction_parameters[0].parameter_data.i;
+ r=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ if (i!=(WORD)i){
+ w_as_opcode ("lis");
+ w_as_register_comma (r);
+ w_as_immediate ((i-(WORD)i)>>16);
+ w_as_newline();
+
+ i=(WORD)i;
+
+ w_as_opcode ("addi");
+ w_as_register_comma (r);
+ w_as_register_comma (r);
+ w_as_immediate (i);
+ w_as_newline();
+ } else {
+ w_as_opcode ("li");
+ w_as_register_comma (r);
+ w_as_immediate (i);
+ w_as_newline();
+ }
+ return;
+ }
+ case P_REGISTER:
+ w_as_opcode ("mr");
+ 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();
+ return;
+ case P_INDIRECT:
+ w_as_opcode (size_flag==SIZE_LONG ? "lwz" :
+ size_flag==SIZE_WORD ? "lha" : "lbz");
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_indirect (instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ w_as_newline();
+ return;
+ case P_INDIRECT_WITH_UPDATE:
+ w_as_opcode (size_flag==SIZE_LONG ? "lwzu" :
+ size_flag==SIZE_WORD ? "lhau" : "lbzu");
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_indirect (instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ w_as_newline();
+ return;
+ case P_INDEXED:
+ w_as_opcode (size_flag==SIZE_LONG ? "lwzx" :
+ size_flag==SIZE_WORD ? "lhax" : "lbzx");
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_indexed (instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.ir);
+ w_as_newline();
+ return;
+ default:
+ internal_error_in_function ("w_as_move_instruction");
+ return;
+ }
+ case P_INDIRECT:
+ {
+ int reg;
+
+ reg=w_as_register_parameter (instruction->instruction_parameters[0],size_flag);
+
+ w_as_opcode (size_flag==SIZE_LONG ? "stw" :
+ size_flag==SIZE_WORD ? "sth" : "stb");
+ w_as_register_comma (reg);
+ w_as_indirect (instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_newline();
+ return;
+ }
+ case P_INDIRECT_WITH_UPDATE:
+ {
+ int reg;
+
+ reg=w_as_register_parameter (instruction->instruction_parameters[0],size_flag);
+
+ w_as_opcode (size_flag==SIZE_LONG ? "stwu" :
+ size_flag==SIZE_WORD ? "sthu" : "stbu");
+
+ w_as_register_comma (reg);
+ w_as_indirect (instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_newline();
+ return;
+ }
+ case P_INDEXED:
+ {
+ int reg;
+
+ reg=w_as_register_parameter (instruction->instruction_parameters[0],size_flag);
+
+ w_as_opcode (size_flag==SIZE_LONG ? "stwx" :
+ size_flag==SIZE_WORD ? "sthx" : "stbx");
+ w_as_register_comma (reg);
+ w_as_indexed (instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.ir);
+ w_as_newline();
+ return;
+ }
+ case P_INDIRECT_HP:
+ {
+ int reg1,reg2;
+ LONG offset;
+
+ reg1=w_as_register_parameter (instruction->instruction_parameters[0],size_flag);
+ offset=instruction->instruction_parameters[1].parameter_data.i;
+ reg2=HEAP_POINTER;
+
+ if (offset!=(WORD)offset){
+ w_as_opcode ("addis");
+ w_as_register_comma (REGISTER_O0);
+ w_as_register_comma (reg2);
+ w_as_immediate ((offset-(WORD)offset)>>16);
+ w_as_newline();
+
+ reg2=REGISTER_O0;
+ offset=(WORD)offset;
+ }
+
+ w_as_opcode (size_flag==SIZE_LONG ? "stw" :
+ size_flag==SIZE_WORD ? "sth" : "stb");
+ w_as_register_comma (reg1);
+ w_as_indirect (offset,reg2);
+ w_as_newline();
+ return;
+ }
+ default:
+ internal_error_in_function ("w_as_move_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_LABEL:
+ w_as_load_label_parameter (&instruction->instruction_parameters[0],
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_INDIRECT:
+ w_as_opcode ("addi");
+ 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 (instruction->instruction_parameters[0].parameter_offset);
+ w_as_newline();
+ return;
+ case P_INDEXED:
+ 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 (instruction->instruction_parameters[0].parameter_data.ir->d_reg.r);
+ w_as_newline();
+ return;
+ }
+
+ internal_error_in_function ("w_as_lea_instruction");
+}
+
+static void w_as_or_or_eor_instruction (struct instruction *instruction,char *opcode)
+{
+ if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){
+ long i;
+
+ i=instruction->instruction_parameters[0].parameter_data.i;
+
+ if ((unsigned short) i != i){
+ int h;
+
+ h=(unsigned)i >> (unsigned)16;
+
+ fprintf (assembly_file,"\t%sis\t",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 (h);
+ w_as_newline();
+
+ i=(unsigned short)i;
+ }
+
+ fprintf (assembly_file,"\t%si\t",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 (i);
+ w_as_newline();
+
+ } else {
+ int reg;
+
+ reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ 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 (reg);
+ w_as_newline();
+ }
+}
+
+static void w_as_tryadic_instruction (struct instruction *instruction,char *opcode)
+{
+ if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){
+ fprintf (assembly_file,"\t%si\t",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_parameter (&instruction->instruction_parameters[0]);
+ w_as_newline();
+ } else {
+ int reg;
+
+ reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ 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 (reg);
+ w_as_newline();
+ }
+}
+
+static void w_as_i_instruction (struct instruction *instruction,char *opcode)
+{
+ 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 (instruction->instruction_parameters[2].parameter_data.i);
+ w_as_newline();
+}
+
+static void w_as_and_instruction (struct instruction *instruction)
+{
+ int reg;
+
+ if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){
+ int i;
+
+ i=instruction->instruction_parameters[0].parameter_data.i;
+
+ if (i==(UWORD)i){
+ w_as_opcode ("andi.");
+
+ 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 (i);
+ w_as_newline();
+
+ return;
+ } else {
+ w_as_opcode ("lis");
+ w_as_register_comma (REGISTER_O0);
+ w_as_immediate ((i-(WORD)i)>>16);
+ w_as_newline();
+
+ i=(WORD)i;
+
+ w_as_opcode ("addi");
+ w_as_register_comma (REGISTER_O0);
+ w_as_register_comma (REGISTER_O0);
+ w_as_immediate (i);
+ w_as_newline();
+
+ reg=REGISTER_O0;
+
+ w_as_opcode ("and");
+ }
+ } else {
+ reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ w_as_opcode ("and");
+ }
+
+ 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 (reg);
+ w_as_newline();
+}
+
+static void w_as_add_instruction (struct instruction *instruction)
+{
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_REGISTER:
+ w_as_opcode ("add");
+ 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 (instruction->instruction_parameters[0].parameter_data.reg.r);
+ w_as_newline();
+ return;
+ case P_IMMEDIATE:
+ {
+ int i,r;
+
+ i=instruction->instruction_parameters[0].parameter_data.i;
+ r=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ if (i!=(WORD)i){
+ w_as_opcode ("addis");
+ w_as_register_comma (r);
+ w_as_register_comma (r);
+ w_as_immediate ((i-(WORD)i)>>16);
+ w_as_newline();
+
+ i=(WORD)i;
+ }
+
+ w_as_opcode ("addi");
+ w_as_register_comma (r);
+ w_as_register_comma (r);
+ w_as_immediate (i);
+ w_as_newline();
+
+ return;
+ }
+ default:
+ {
+ int reg;
+
+ reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ w_as_opcode ("add");
+ 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 (reg);
+ w_as_newline();
+ }
+ }
+}
+
+static void w_as_extb_instruction (struct instruction *instruction)
+{
+ int reg;
+
+ reg=instruction->instruction_parameters[0].parameter_data.reg.r;
+
+ w_as_opcode ("extsb");
+ w_as_register_comma (reg);
+ w_as_register (reg);
+ w_as_newline();
+}
+
+static void w_as_addo_instruction (struct instruction *instruction)
+{
+ int reg;
+
+ reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ w_as_opcode ("addo.");
+ 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 (reg);
+ w_as_newline();
+}
+
+static void w_as_sub_instruction (struct instruction *instruction)
+{
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_REGISTER:
+ w_as_opcode ("sub");
+ 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 (instruction->instruction_parameters[0].parameter_data.reg.r);
+ w_as_newline();
+ return;
+ case P_IMMEDIATE:
+ {
+ int i,r;
+
+ i= -instruction->instruction_parameters[0].parameter_data.i;
+ r=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ if (i!=(WORD)i){
+ w_as_opcode ("addis");
+ w_as_register_comma (r);
+ w_as_register_comma (r);
+ w_as_immediate ((i-(WORD)i)>>16);
+ w_as_newline();
+
+ i=(WORD)i;
+ }
+
+ w_as_opcode ("addi");
+ w_as_register_comma (r);
+ w_as_register_comma (r);
+ w_as_immediate (i);
+ w_as_newline();
+
+ return;
+ }
+ default:
+ {
+ int reg;
+
+ reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ w_as_opcode ("sub");
+ 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 (reg);
+ w_as_newline();
+ }
+ }
+}
+
+static void w_as_subo_instruction (struct instruction *instruction)
+{
+ int reg;
+
+ reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ w_as_opcode ("subo.");
+ 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 (reg);
+ w_as_newline();
+}
+
+static void w_as_cmp_instruction (struct instruction *instruction,int size_flag)
+{
+ struct parameter parameter_0,parameter_1;
+
+ parameter_0=instruction->instruction_parameters[0];
+ parameter_1=instruction->instruction_parameters[1];
+
+ if (parameter_1.parameter_type==P_INDIRECT || parameter_1.parameter_type==P_INDEXED){
+ if (parameter_1.parameter_type==P_INDIRECT)
+ w_as_opcode (size_flag==SIZE_LONG ? "lwz" : "lha");
+ else
+ w_as_opcode (size_flag==SIZE_LONG ? "lwzx" : "lhax");
+
+ w_as_register_comma (REGISTER_O1);
+ w_as_parameter (&parameter_1);
+ w_as_newline();
+
+ parameter_1.parameter_type=P_REGISTER;
+ parameter_1.parameter_data.reg.r=REGISTER_O1;
+ }
+
+ switch (parameter_0.parameter_type){
+ case P_DESCRIPTOR_NUMBER:
+ w_as_load_descriptor (&parameter_0,REGISTER_O0);
+
+ parameter_0.parameter_type=P_REGISTER;
+ parameter_0.parameter_data.reg.r=REGISTER_O0;
+ break;
+ case P_REGISTER:
+ break;
+ case P_IMMEDIATE:
+ {
+ int i;
+
+ i=parameter_0.parameter_data.i;
+
+ if (i!=(WORD)i){
+ w_as_opcode ("lis");
+ w_as_register_comma (REGISTER_O0);
+ w_as_immediate ((i-(WORD)i)>>16);
+ w_as_newline();
+
+ i=(WORD)i;
+
+ w_as_opcode ("addi");
+ w_as_register_comma (REGISTER_O0);
+ w_as_register_comma (REGISTER_O0);
+ w_as_immediate (i);
+ w_as_newline();
+
+ parameter_0.parameter_type=P_REGISTER;
+ parameter_0.parameter_data.reg.r=REGISTER_O0;
+ }
+ break;
+ }
+ case P_INDIRECT:
+ switch (size_flag){
+ case SIZE_WORD:
+ w_as_opcode ("lha");
+ break;
+ case SIZE_LONG:
+ w_as_opcode ("lwz");
+ break;
+ default:
+ internal_error_in_function ("w_as_cmp_instruction");
+ }
+ w_as_register_comma (REGISTER_O0);
+ w_as_parameter (&parameter_0);
+ w_as_newline();
+
+ parameter_0.parameter_type=P_REGISTER;
+ parameter_0.parameter_data.reg.r=REGISTER_O0;
+ break;
+ case P_INDEXED:
+ switch (size_flag){
+ case SIZE_WORD:
+ w_as_opcode ("lhax");
+ break;
+ case SIZE_LONG:
+ w_as_opcode ("lwzx");
+ break;
+ default:
+ internal_error_in_function ("w_as_cmp_instruction");
+ }
+ w_as_register_comma (REGISTER_O0);
+ w_as_parameter (&parameter_0);
+ w_as_newline();
+
+ parameter_0.parameter_type=P_REGISTER;
+ parameter_0.parameter_data.reg.r=REGISTER_O0;
+ break;
+ }
+
+ w_as_opcode (parameter_0.parameter_type==P_IMMEDIATE ? "cmpwi" : "cmpw");
+ w_as_immediate (0);
+ w_as_comma();
+ w_as_parameter (&parameter_1);
+ w_as_comma();
+ w_as_parameter (&parameter_0);
+ w_as_newline();
+}
+
+static void w_as_cmplw_instruction (struct instruction *instruction)
+{
+ w_as_opcode ("lwz");
+ w_as_register_comma (REGISTER_O0);
+ w_as_parameter (&instruction->instruction_parameters[0]);
+ w_as_newline();
+
+ w_as_opcode ("cmplw");
+ w_as_immediate (0);
+ w_as_comma();
+ w_as_parameter (&instruction->instruction_parameters[1]);
+ w_as_comma();
+ w_as_register (REGISTER_O0);
+ w_as_newline();
+}
+
+static void w_as_tst_instruction (struct instruction *instruction)
+{
+ int reg;
+
+ reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ w_as_opcode ("cmpwi");
+ w_as_immediate (0);
+ w_as_comma();
+ w_as_register_comma (reg);
+ w_as_immediate (0);
+ w_as_newline();
+}
+
+static void w_as_btst_instruction (struct instruction *instruction)
+{
+ w_as_opcode ("andi.");
+ w_as_register_comma (REGISTER_O0);
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_immediate (instruction->instruction_parameters[0].parameter_data.i);
+ w_as_newline();
+}
+
+void w_as_jmp_instruction (struct instruction *instruction)
+{
+ struct parameter *parameter0;
+
+ parameter0=&instruction->instruction_parameters[0];
+
+ switch (parameter0->parameter_type){
+ case P_LABEL:
+ w_as_opcode ("b");
+ if (parameter0->parameter_data.l->label_number!=0)
+ w_as_local_label (parameter0->parameter_data.l->label_number);
+ else
+ w_as_label (parameter0->parameter_data.l->label_name);
+
+ w_as_newline();
+ return;
+ case P_INDIRECT:
+ {
+ int offset,reg;
+
+ offset=parameter0->parameter_offset;
+ reg=parameter0->parameter_data.reg.r;
+
+ if (offset!=0){
+ w_as_opcode ("la");
+ w_as_register_comma (REGISTER_O0);
+ w_as_indirect (offset,reg);
+ w_as_newline();
+
+ w_as_opcode ("mtctr");
+ w_as_register (REGISTER_O0);
+ w_as_newline();
+ } else {
+ w_as_opcode ("mtctr");
+ w_as_register (reg);
+ w_as_newline();
+ }
+
+ w_as_instruction_without_parameters ("bctr");
+ return;
+ }
+ default:
+ internal_error_in_function ("w_as_jmp_instruction");
+ }
+}
+
+static void w_as_jmpp_instruction (struct instruction *instruction)
+{
+ struct parameter *parameter0;
+
+ parameter0=&instruction->instruction_parameters[0];
+
+ switch (parameter0->parameter_type){
+ case P_LABEL:
+ {
+ int offset;
+
+ offset=instruction->instruction_parameters[0].parameter_offset;
+ if (offset==0){
+ w_as_opcode ("mflr");
+ w_as_register (REGISTER_R0);
+ w_as_newline();
+
+ w_as_opcode ("bl");
+ w_as_label ("profile_t");
+ w_as_newline();
+ }
+
+ w_as_opcode ("b");
+ if (instruction->instruction_parameters[0].parameter_data.l->label_number!=0)
+ w_as_local_label (instruction->instruction_parameters[0].parameter_data.l->label_number);
+ else
+ w_as_label (instruction->instruction_parameters[0].parameter_data.l->label_name);
+
+ if (offset!=0)
+ fprintf (assembly_file,"+%d",offset);
+
+ w_as_newline();
+ return;
+ }
+ case P_INDIRECT:
+ {
+ int offset,reg;
+
+ offset=parameter0->parameter_offset;
+ reg=parameter0->parameter_data.reg.r;
+
+ if (offset!=0){
+ w_as_opcode ("la");
+ w_as_register_comma (REGISTER_O0);
+ w_as_indirect (offset,reg);
+ w_as_newline();
+
+ w_as_opcode ("mtctr");
+ w_as_register (REGISTER_O0);
+ w_as_newline();
+ } else {
+ w_as_opcode ("mtctr");
+ w_as_register (reg);
+ w_as_newline();
+ }
+
+ w_as_opcode ("b");
+ w_as_label ("profile_ti");
+ w_as_newline();
+ return;
+ }
+ default:
+ internal_error_in_function ("w_as_jmpp_instruction");
+ }
+}
+
+struct call_and_jump {
+ struct call_and_jump * cj_next;
+ WORD cj_label_id;
+ WORD cj_jump_id; /* or -1 for far conditional jump */
+ char * cj_call_label_name;
+};
+
+static struct call_and_jump *first_call_and_jump,*last_call_and_jump;
+
+static struct call_and_jump *allocate_new_call_and_jump (void)
+{
+ struct call_and_jump *new_call_and_jump;
+
+ new_call_and_jump=allocate_memory_from_heap_type (struct call_and_jump);
+
+ new_call_and_jump->cj_next=NULL;
+
+ 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;
+
+ return new_call_and_jump;
+}
+
+static void w_as_branch_instruction (struct instruction *instruction,char *opcode)
+{
+ w_as_opcode (opcode);
+
+ if (instruction->instruction_parameters[0].parameter_data.l->label_flags & FAR_CONDITIONAL_JUMP_LABEL){
+ struct call_and_jump *new_call_and_jump;
+ int label_id;
+
+ label_id=next_label_id++;
+
+ new_call_and_jump=allocate_new_call_and_jump();
+
+ new_call_and_jump->cj_call_label_name=instruction->instruction_parameters[0].parameter_data.l->label_name;
+ new_call_and_jump->cj_label_id=label_id;
+ new_call_and_jump->cj_jump_id=-1;
+
+ w_as_internal_label (label_id);
+ } else
+ w_as_parameter (&instruction->instruction_parameters[0]);
+
+ w_as_newline();
+}
+
+static void w_as_index_error_branch_instruction (struct instruction *instruction)
+{
+ w_as_opcode ("blt+");
+ fprintf (assembly_file,".+8");
+ w_as_newline();
+
+ w_as_opcode ("b");
+ w_as_parameter (&instruction->instruction_parameters[0]);
+ w_as_newline();
+}
+
+static void w_as_branchno_instruction (struct instruction *instruction)
+{
+ w_as_opcode ("bns");
+ w_as_parameter (&instruction->instruction_parameters[0]);
+ w_as_newline();
+
+ w_as_opcode ("mcrxr");
+ w_as_immediate (0);
+ w_as_newline();
+
+ w_as_opcode ("bng");
+ w_as_parameter (&instruction->instruction_parameters[0]);
+ w_as_newline();
+}
+
+static void w_as_brancho_instruction (struct instruction *instruction)
+{
+ w_as_opcode ("bns");
+ fprintf (assembly_file,IF_GNU ("$+12","*+12"));
+ w_as_newline();
+
+ w_as_opcode ("mcrxr");
+ w_as_immediate (0);
+ w_as_newline();
+
+ w_as_opcode ("bgt");
+ w_as_parameter (&instruction->instruction_parameters[0]);
+ w_as_newline();
+}
+
+#ifdef MACH_O
+struct stub {
+ char *stub_label_name;
+ struct stub *stub_next;
+};
+
+static struct stub *first_stub,**next_stub_l;
+
+static void write_stub (char *label_name,int stub_n)
+{
+ fprintf (assembly_file,".picsymbol_stub" NEWLINE_STRING);
+ fprintf (assembly_file,"L_%s$stub:" NEWLINE_STRING,label_name);
+ fprintf (assembly_file,"\t.indirect_symbol _%s" NEWLINE_STRING,label_name);
+ fprintf (assembly_file,"\tmflr\tr0" NEWLINE_STRING);
+ fprintf (assembly_file,"\tbcl\t20,31,L%d$pb" NEWLINE_STRING,stub_n);
+ fprintf (assembly_file,"L%d$pb:" NEWLINE_STRING,stub_n);
+ fprintf (assembly_file,"\tmflr\tr11" NEWLINE_STRING);
+ fprintf (assembly_file,"\taddis\tr11,r11,ha16(L%d$lz-L%d$pb)" NEWLINE_STRING,stub_n,stub_n);
+ fprintf (assembly_file,"\tmtlr\tr0" NEWLINE_STRING);
+ fprintf (assembly_file,"\tlwz\tr12,lo16(L%d$lz-L%d$pb)(r11)" NEWLINE_STRING,stub_n,stub_n);
+ fprintf (assembly_file,"\tmtctr\tr12" NEWLINE_STRING);
+ fprintf (assembly_file,"\taddi\tr11,r11,lo16(L%d$lz-L%d$pb )" NEWLINE_STRING,stub_n,stub_n);
+ fprintf (assembly_file,"\tbctr" NEWLINE_STRING);
+ fprintf (assembly_file,".lazy_symbol_pointer" NEWLINE_STRING);
+ fprintf (assembly_file,"L%d$lz:" NEWLINE_STRING,stub_n);
+ fprintf (assembly_file,".indirect_symbol _%s" NEWLINE_STRING,label_name);
+ fprintf (assembly_file,"\t.long\tdyld_stub_binding_helper" NEWLINE_STRING);
+}
+
+static void write_stubs (void)
+{
+ struct stub *stub;
+ int stub_n;
+
+ stub_n=1;
+ for_l (stub,first_stub,stub_next){
+ write_stub (stub->stub_label_name,stub_n);
+ ++stub_n;
+ }
+
+}
+#endif
+
+static void w_as_jsr_instruction (struct instruction *instruction)
+{
+ struct parameter *parameter0;
+
+ parameter0=&instruction->instruction_parameters[0];
+
+ if (instruction->instruction_parameters[1].parameter_type==P_REGISTER){
+ int frame_size;
+
+ frame_size=instruction->instruction_parameters[1].parameter_data.i;
+
+ if (parameter0->parameter_type==P_REGISTER){
+ w_as_opcode ("mtctr");
+ w_as_register (parameter0->parameter_data.reg.r);
+ w_as_newline();
+ }
+
+ if (!(instruction->instruction_arity & NO_MFLR)){
+ w_as_opcode ("mflr");
+ w_as_register (REGISTER_R0);
+ w_as_newline();
+ }
+
+#ifdef ALIGN_C_CALLS
+# if 0
+ w_as_opcode ("mr");
+ w_as_register_comma (REGISTER_O0);
+ w_as_register (B_STACK_POINTER);
+ w_as_newline();
+
+ w_as_opcode ("ori");
+ w_as_register_comma (B_STACK_POINTER);
+ w_as_register_comma (B_STACK_POINTER);
+ w_as_immediate (28);
+ w_as_newline();
+# endif
+ w_as_opcode ("stw");
+ w_as_register_comma (REGISTER_R0);
+ w_as_indirect (-28-4,REGISTER_SP);
+ w_as_newline();
+
+ w_as_opcode ("stwu");
+ w_as_register_comma (REGISTER_O0);
+ w_as_indirect (-(frame_size+28),REGISTER_SP);
+ w_as_newline();
+#else
+ w_as_opcode ("stw");
+ w_as_register_comma (REGISTER_R0);
+ w_as_indirect (-4,REGISTER_SP);
+ w_as_newline();
+
+ w_as_opcode ("stwu");
+ w_as_register_comma (REGISTER_SP);
+ w_as_indirect (-frame_size,REGISTER_SP);
+ w_as_newline();
+#endif
+
+ if (parameter0->parameter_type==P_REGISTER){
+ w_as_instruction_without_parameters ("bctrl");
+ } else {
+ w_as_opcode ("bl");
+ if (parameter0->parameter_data.l->label_number!=0)
+ w_as_local_label (parameter0->parameter_data.l->label_number);
+ else
+#ifdef MACH_O
+ {
+ char *label_name;
+
+ label_name=parameter0->parameter_data.l->label_name;
+ if (label_name[0]=='_'){
+ int c;
+ struct stub *new_stub;
+
+ putc ('L',assembly_file);
+ putc ('_',assembly_file);
+ ++label_name;
+
+ if (!(parameter0->parameter_data.l->label_flags & STUB_GENERATED)){
+ parameter0->parameter_data.l->label_flags |= STUB_GENERATED;
+
+ new_stub=allocate_memory_from_heap (sizeof (struct stub));
+
+ new_stub->stub_label_name=label_name;
+ *next_stub_l=new_stub;
+ next_stub_l=&new_stub->stub_next;
+ new_stub->stub_next=NULL;
+ }
+
+ while (c=*label_name++,c!=0)
+ putc (c,assembly_file);
+
+ fprintf (assembly_file,"$stub");
+ } else
+ w_as_label (label_name);
+
+ }
+#else
+ w_as_label (parameter0->parameter_data.l->label_name);
+#endif
+ w_as_newline();
+ }
+
+ w_as_instruction_without_parameters ("nop");
+
+#ifdef ALIGN_C_CALLS
+ w_as_opcode ("lwz");
+ w_as_register_comma (REGISTER_R0);
+ w_as_indirect (frame_size-4,REGISTER_SP);
+ w_as_newline();
+
+ w_as_opcode ("lwz");
+ w_as_register_comma (REGISTER_SP);
+ w_as_indirect (0,REGISTER_SP);
+ w_as_newline();
+#else
+ w_as_opcode ("lwz");
+ w_as_register_comma (REGISTER_R0);
+ w_as_indirect (frame_size-4,REGISTER_SP);
+ w_as_newline();
+
+ w_as_opcode ("addi");
+ w_as_register_comma (REGISTER_SP);
+ w_as_register_comma (REGISTER_SP);
+ w_as_immediate (frame_size);
+ w_as_newline();
+#endif
+
+ if (!(instruction->instruction_arity & NO_MTLR)){
+ w_as_opcode ("mtlr");
+ w_as_register (REGISTER_R0);
+ w_as_newline();
+ }
+ return;
+ }
+
+
+ if (parameter0->parameter_type==P_INDIRECT){
+ int offset,reg;
+
+ offset=parameter0->parameter_offset;
+ reg=parameter0->parameter_data.reg.r;
+
+ if (offset!=0){
+ w_as_opcode ("la");
+ w_as_register_comma (REGISTER_O0);
+ w_as_indirect (offset,reg);
+ w_as_newline();
+
+ w_as_opcode ("mtctr");
+ w_as_register (REGISTER_O0);
+ w_as_newline();
+ } else {
+ w_as_opcode ("mtctr");
+ w_as_register (reg);
+ w_as_newline();
+ }
+ }
+
+ if (!(instruction->instruction_arity & NO_MFLR)){
+ w_as_opcode ("mflr");
+ w_as_register (REGISTER_R0);
+ w_as_newline();
+ }
+
+ w_as_opcode (instruction->instruction_parameters[1].parameter_type==P_INDIRECT_WITH_UPDATE
+ ? "stwu" : "stw");
+ w_as_register_comma (REGISTER_R0);
+ w_as_indirect (instruction->instruction_parameters[1].parameter_data.i,B_STACK_POINTER);
+ w_as_newline();
+
+ switch (parameter0->parameter_type){
+ case P_LABEL:
+ w_as_opcode ("bl");
+ if (parameter0->parameter_data.l->label_number!=0)
+ w_as_local_label (parameter0->parameter_data.l->label_number);
+ else
+ w_as_label (parameter0->parameter_data.l->label_name);
+ break;
+ case P_INDIRECT:
+ w_as_opcode ("bctrl");
+ break;
+ default:
+ internal_error_in_function ("w_as_jsr_instruction");
+ }
+ w_as_newline();
+
+ if (!(instruction->instruction_arity & NO_MTLR)){
+ w_as_opcode ("mtlr");
+ w_as_register (REGISTER_R0);
+ w_as_newline();
+ }
+}
+
+static void w_as_call_and_jump (struct call_and_jump *call_and_jump)
+{
+ w_as_new_code_module();
+
+ w_as_define_internal_label (call_and_jump->cj_label_id);
+
+ if (call_and_jump->cj_jump_id==-1){
+ w_as_opcode ("b");
+ w_as_label (call_and_jump->cj_call_label_name);
+ w_as_newline();
+ } else {
+ w_as_opcode ("mflr");
+ w_as_register (REGISTER_R0);
+ w_as_newline();
+
+ w_as_opcode ("bl");
+ w_as_label (call_and_jump->cj_call_label_name);
+ w_as_newline();
+
+ w_as_opcode ("b");
+ w_as_internal_label (call_and_jump->cj_jump_id);
+ w_as_newline();
+ }
+}
+
+static void w_as_rts_begin (struct instruction *instruction)
+{
+ LONG b_offset;
+
+ if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT){
+ w_as_opcode ("lwz");
+ w_as_register_comma (REGISTER_R0);
+ w_as_indirect (instruction->instruction_parameters[0].parameter_offset,instruction->instruction_parameters[0].parameter_data.reg.r);
+ } else {
+ w_as_opcode ("mr");
+ w_as_register_comma (REGISTER_R0);
+ w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r);
+ }
+ w_as_newline();
+
+ b_offset=instruction->instruction_parameters[1].parameter_data.i;
+ if (b_offset!=0){
+ if (b_offset!=(WORD) b_offset){
+ w_as_opcode ("addis");
+ w_as_register_comma (B_STACK_POINTER);
+ w_as_register_comma (B_STACK_POINTER);
+ w_as_immediate ((b_offset-(WORD)b_offset)>>16);
+ w_as_newline();
+
+ b_offset=(WORD)b_offset;
+ }
+
+ w_as_opcode ("addi");
+ w_as_register_comma (B_STACK_POINTER);
+ w_as_register_comma (B_STACK_POINTER);
+ w_as_immediate (b_offset);
+ w_as_newline();
+ }
+}
+
+static void w_as_rts_instruction (struct instruction *instruction)
+{
+ if (instruction->instruction_arity>0)
+ w_as_rts_begin (instruction);
+
+ w_as_instruction_without_parameters ("blr");
+}
+
+static void w_as_rtsp_instruction (struct instruction *instruction)
+{
+ w_as_rts_begin (instruction);
+
+ w_as_opcode ("b");
+ w_as_label ("profile_r");
+ w_as_newline();
+}
+
+static void w_as_set_condition_instruction (struct instruction *instruction,char *opcode)
+{
+ w_as_opcode ("li");
+ w_as_parameter (&instruction->instruction_parameters[0]);
+ w_as_comma();
+ w_as_immediate (0);
+ w_as_newline();
+
+ w_as_opcode (opcode);
+ fprintf (assembly_file,IF_GNU ("$+8","*+8"));
+ w_as_newline();
+
+ w_as_opcode ("li");
+ w_as_parameter (&instruction->instruction_parameters[0]);
+ w_as_comma();
+ w_as_immediate (-1);
+ w_as_newline();
+}
+
+static void w_as_setno_condition_instruction (struct instruction *instruction)
+{
+ w_as_opcode ("li");
+ w_as_parameter (&instruction->instruction_parameters[0]);
+ w_as_comma();
+ w_as_immediate (0);
+ w_as_newline();
+
+ w_as_opcode ("bns");
+ fprintf (assembly_file,IF_GNU ("$+12","*+12"));
+ w_as_newline();
+
+ w_as_opcode ("mcrxr");
+ w_as_immediate (0);
+ w_as_newline();
+
+ w_as_opcode ("bgt");
+ fprintf (assembly_file,IF_GNU ("$+8","*+8"));
+ w_as_newline();
+
+ w_as_opcode ("li");
+ w_as_parameter (&instruction->instruction_parameters[0]);
+ w_as_comma();
+ w_as_immediate (-1);
+ w_as_newline();
+}
+
+static void w_as_seto_condition_instruction (struct instruction *instruction)
+{
+ w_as_opcode ("li");
+ w_as_parameter (&instruction->instruction_parameters[0]);
+ w_as_comma();
+ w_as_immediate (0);
+ w_as_newline();
+
+ w_as_opcode ("bns");
+ fprintf (assembly_file,IF_GNU ("$+16","*+16"));
+ w_as_newline();
+
+ w_as_opcode ("mcrxr");
+ w_as_immediate (0);
+ w_as_newline();
+
+ w_as_opcode ("bng");
+ fprintf (assembly_file,IF_GNU ("$+8","*+8"));
+ w_as_newline();
+
+ w_as_opcode ("li");
+ w_as_parameter (&instruction->instruction_parameters[0]);
+ w_as_comma();
+ w_as_immediate (-1);
+ w_as_newline();
+}
+
+static void w_as_rem_instruction (struct instruction *instruction)
+{
+ int reg;
+
+ if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){
+ int i,sd_reg;
+
+ i=instruction->instruction_parameters[0].parameter_data.i;
+ if ((i & (i-1))==0 && i>1){
+ int log2i;
+
+ log2i=0;
+ while (i>1){
+ i=i>>1;
+ ++log2i;
+ }
+
+ sd_reg=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ w_as_opcode ("srawi");
+ w_as_register_comma (REGISTER_O1);
+ w_as_register_comma (sd_reg);
+ w_as_immediate (31);
+ w_as_newline();
+
+ if (log2i==1){
+ w_as_opcode ("andi.");
+ w_as_register_comma (sd_reg);
+ w_as_register_comma (sd_reg);
+ w_as_immediate (1);
+ w_as_newline();
+
+ w_as_opcode ("xor");
+ w_as_register_comma (sd_reg);
+ w_as_register_comma (sd_reg);
+ w_as_register_newline (REGISTER_O1);
+ } else {
+ w_as_opcode ("rlwinm");
+ w_as_register_comma (REGISTER_O1);
+ w_as_register_comma (REGISTER_O1);
+ w_as_immediate (0);
+ w_as_comma();
+ w_as_immediate (32-log2i);
+ w_as_comma();
+ w_as_immediate (31);
+ w_as_newline();
+
+ w_as_opcode ("add");
+ w_as_register_comma (sd_reg);
+ w_as_register_comma (sd_reg);
+ w_as_register_newline (REGISTER_O1);
+
+ w_as_opcode ("rlwinm");
+ w_as_register_comma (sd_reg);
+ w_as_register_comma (sd_reg);
+ w_as_immediate (0);
+ w_as_comma();
+ w_as_immediate (32-log2i);
+ w_as_comma();
+ w_as_immediate (31);
+ w_as_newline();
+ }
+
+ w_as_opcode ("sub");
+ w_as_register_comma (sd_reg);
+ w_as_register_comma (sd_reg);
+ w_as_register_newline (REGISTER_O1);
+
+ return;
+ }
+ }
+
+ reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ w_as_opcode ("divw");
+ w_as_register_comma (REGISTER_O1);
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_register_newline (reg);
+
+ w_as_opcode ("mullw");
+ w_as_register_comma (REGISTER_O1);
+ w_as_register_comma (REGISTER_O1);
+ w_as_register_newline (reg);
+
+ w_as_opcode ("sub");
+ 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 (REGISTER_O1);
+}
+
+static void w_as_div_instruction (struct instruction *instruction)
+{
+ int reg;
+
+ if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){
+ int i,sd_reg;
+
+ i=instruction->instruction_parameters[0].parameter_data.i;
+ if ((i & (i-1))==0 && i>0){
+ int log2i;
+
+ if (i==1)
+ return;
+
+ log2i=0;
+ while (i>1){
+ i=i>>1;
+ ++log2i;
+ }
+
+ sd_reg=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ w_as_opcode ("srawi");
+ w_as_register_comma (sd_reg);
+ w_as_register_comma (sd_reg);
+ w_as_immediate (log2i);
+ w_as_newline();
+
+ w_as_opcode ("addze");
+ w_as_register_comma (sd_reg);
+ w_as_register_newline (sd_reg);
+
+ return;
+ }
+ }
+
+ reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ w_as_opcode ("divw");
+
+ 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 (reg);
+}
+
+static void w_as_mul_instruction (struct instruction *instruction)
+{
+ int r,reg;
+
+ r=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_IMMEDIATE:
+ {
+ int i;
+
+ i=instruction->instruction_parameters[0].parameter_data.i;
+
+ if (i!=(WORD)i){
+ w_as_opcode ("lis");
+ w_as_register_comma (REGISTER_O0);
+ w_as_immediate ((i-(WORD)i)>>16);
+ w_as_newline();
+
+ i=(WORD)i;
+
+ w_as_opcode ("addi");
+ w_as_register_comma (REGISTER_O0);
+ w_as_register_comma (REGISTER_O0);
+ w_as_immediate (i);
+ w_as_newline();
+ } else {
+ w_as_opcode ("mulli");
+ w_as_register_comma (r);
+ w_as_register_comma (r);
+ w_as_immediate (i);
+ w_as_newline();
+
+ return;
+ }
+
+ reg=REGISTER_O0;
+ break;
+ }
+ default:
+ reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+ }
+
+ w_as_opcode ("mullw");
+
+ w_as_register_comma (r);
+ w_as_register_comma (r);
+ w_as_register (reg);
+ w_as_newline();
+}
+
+static void w_as_mulo_instruction (struct instruction *instruction)
+{
+ int r,reg;
+
+ reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
+
+ r=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ w_as_opcode ("mullwo.");
+
+ w_as_register_comma (r);
+ w_as_register_comma (r);
+ w_as_register (reg);
+ w_as_newline();
+}
+
+static int next_bmove_label;
+
+static void w_as_word_instruction (struct instruction *instruction)
+{
+ fprintf (assembly_file,"\t" DC_L "\t%d" NEWLINE_STRING,
+ (int)instruction->instruction_parameters[0].parameter_data.i);
+}
+
+static void w_as_load_float_immediate (double float_value,int fp_reg)
+{
+ int label_number,t_label_number;
+ struct label *new_label;
+
+ new_label=(struct label*)allocate_memory_from_heap (sizeof (struct label));
+
+ label_number=next_label_id++;
+
+ w_as_to_data_section();
+#ifdef GNU_SYNTAX
+ fprintf (assembly_file,"\t.align\t8" NEWLINE_STRING);
+#else
+ fprintf (assembly_file,"\talign\t3" NEWLINE_STRING);
+#endif
+ new_label->label_flags=0;
+ new_label->label_number=label_number;
+
+ /* w_as_define_internal_label (label_number); */
+
+ w_as_define_local_label (label_number);
+#ifdef GNU_SYNTAX
+ w_as_opcode (".double");
+ fprintf (assembly_file,"0d%.20e",float_value);
+#else
+ w_as_opcode ("dc.d");
+ fprintf (assembly_file,"\"%.20e\"",float_value);
+#endif
+ w_as_newline();
+
+/*
+ w_as_instruction_without_parameters ("toc");
+
+ w_as_opcode ("tc");
+ fprintf (assembly_file,"t_%d{TC}",t_label_number);
+ w_as_comma();
+ w_as_internal_label (label_number);
+ w_as_newline();
+*/
+
+#ifndef GNU_SYNTAX
+ t_label_number=make_toc_label (new_label,0);
+#endif
+ w_as_to_code_section();
+
+ w_as_opcode (IF_GNU ("lis","lwz"));
+ w_as_scratch_register();
+ w_as_comma();
+#ifdef GNU_SYNTAX
+# ifdef MACH_O
+ fprintf (assembly_file,"ha16(");
+# endif
+ w_as_local_label (label_number);
+# ifdef MACH_O
+ fprintf (assembly_file,")" NEWLINE_STRING);
+# else
+ fprintf (assembly_file,"@ha" NEWLINE_STRING);
+# endif
+#else
+ fprintf (assembly_file,"t_%d{TC}(RTOC)" NEWLINE_STRING,t_label_number);
+#endif
+
+ w_as_opcode ("lfd");
+ w_as_fp_register (fp_reg);
+ w_as_comma();
+#ifdef GNU_SYNTAX
+# ifdef MACH_O
+ fprintf (assembly_file,"lo16(");
+# endif
+ w_as_local_label (label_number);
+# ifdef MACH_O
+ fprintf (assembly_file,")(");
+# else
+ fprintf (assembly_file,"@l(");
+# endif
+ w_as_scratch_register();
+ fprintf (assembly_file,")" NEWLINE_STRING);
+#else
+ w_as_indirect (0,REGISTER_O0);
+ w_as_newline();
+#endif
+ /*++t_label_number; */
+}
+
+static struct parameter w_as_float_parameter (struct parameter parameter)
+{
+ switch (parameter.parameter_type){
+ case P_F_IMMEDIATE:
+ w_as_load_float_immediate (*parameter.parameter_data.r,17);
+
+ parameter.parameter_type=P_F_REGISTER;
+ parameter.parameter_data.reg.r=17;
+ break;
+ case P_INDIRECT:
+ w_as_opcode ("lfd");
+ w_as_fp_register (17);
+ w_as_comma();
+ w_as_indirect (parameter.parameter_offset,parameter.parameter_data.reg.r);
+ w_as_newline();
+
+ parameter.parameter_type=P_F_REGISTER;
+ parameter.parameter_data.reg.r=17;
+ break;
+ case P_INDEXED:
+ w_as_opcode ("lfdx");
+ w_as_fp_register (17);
+ w_as_comma();
+ w_as_indexed (parameter.parameter_offset,parameter.parameter_data.ir);
+ w_as_newline();
+
+ parameter.parameter_type=P_F_REGISTER;
+ parameter.parameter_data.reg.r=17;
+ break;
+ }
+ return parameter;
+}
+
+static void w_as_compare_float_instruction (struct instruction *instruction)
+{
+ struct parameter parameter_0;
+
+ parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]);
+
+ w_as_opcode ("fcmpu");
+
+ w_as_immediate (0);
+ w_as_comma();
+ w_as_parameter (&instruction->instruction_parameters[1]);
+ w_as_comma();
+ w_as_parameter (&parameter_0);
+ w_as_newline();
+}
+
+static void w_as_dyadic_float_instruction (struct instruction *instruction,char *opcode)
+{
+ struct parameter parameter_0;
+
+ parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]);
+
+ w_as_opcode (opcode);
+
+ w_as_parameter (&instruction->instruction_parameters[1]);
+ w_as_comma();
+ w_as_parameter (&parameter_0);
+ w_as_newline();
+}
+
+static void w_as_tryadic_float_instruction (struct instruction *instruction,char *opcode)
+{
+ struct parameter parameter_0;
+
+ parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]);
+
+ w_as_opcode (opcode);
+
+ w_as_parameter (&instruction->instruction_parameters[1]);
+ w_as_comma();
+ w_as_parameter (&instruction->instruction_parameters[1]);
+ w_as_comma();
+ w_as_parameter (&parameter_0);
+ w_as_newline();
+}
+
+#ifdef FMADD
+#define FP_REG_LAST_USE 4
+
+static struct instruction *w_as_fmul_instruction (struct instruction *instruction)
+{
+ struct instruction *next_instruction;
+
+ next_instruction=instruction->instruction_next;
+ if (fmadd_flag && next_instruction!=NULL)
+ if (next_instruction->instruction_icode==IFADD){
+ if (next_instruction->instruction_parameters[0].parameter_type==P_F_REGISTER &&
+ next_instruction->instruction_parameters[0].parameter_data.reg.r!=next_instruction->instruction_parameters[1].parameter_data.reg.r)
+ {
+ if (next_instruction->instruction_parameters[0].parameter_flags & FP_REG_LAST_USE &&
+ next_instruction->instruction_parameters[0].parameter_data.reg.r==instruction->instruction_parameters[1].parameter_data.reg.r)
+ {
+ struct parameter parameter_0;
+
+ parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]);
+
+ w_as_opcode ("fmadd");
+
+ w_as_parameter (&next_instruction->instruction_parameters[1]);
+ w_as_comma();
+ w_as_parameter (&parameter_0);
+ w_as_comma();
+ w_as_parameter (&instruction->instruction_parameters[1]);
+ w_as_comma();
+ w_as_parameter (&next_instruction->instruction_parameters[1]);
+ w_as_newline();
+
+ return next_instruction;
+ } else if (next_instruction->instruction_parameters[1].parameter_data.reg.r==instruction->instruction_parameters[1].parameter_data.reg.r){
+ struct parameter parameter_0;
+
+ parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]);
+
+ w_as_opcode ("fmadd");
+
+ w_as_parameter (&next_instruction->instruction_parameters[1]);
+ w_as_comma();
+ w_as_parameter (&parameter_0);
+ w_as_comma();
+ w_as_parameter (&instruction->instruction_parameters[1]);
+ w_as_comma();
+ w_as_parameter (&next_instruction->instruction_parameters[0]);
+ w_as_newline();
+
+ return next_instruction;
+ }
+ }
+ } else if (next_instruction->instruction_icode==IFSUB){
+ if (next_instruction->instruction_parameters[0].parameter_type==P_F_REGISTER &&
+ next_instruction->instruction_parameters[0].parameter_data.reg.r!=next_instruction->instruction_parameters[1].parameter_data.reg.r)
+ {
+ if (next_instruction->instruction_parameters[0].parameter_flags & FP_REG_LAST_USE &&
+ next_instruction->instruction_parameters[0].parameter_data.reg.r==instruction->instruction_parameters[1].parameter_data.reg.r)
+ {
+ struct parameter parameter_0;
+
+ parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]);
+
+# ifdef FSUB_FDIV_REVERSED
+ if (next_instruction->instruction_parameters[1].parameter_flags)
+ w_as_opcode ("fmsub");
+ else
+# endif
+ w_as_opcode ("fnmsub");
+
+ w_as_parameter (&next_instruction->instruction_parameters[1]);
+ w_as_comma();
+ w_as_parameter (&parameter_0);
+ w_as_comma();
+ w_as_parameter (&instruction->instruction_parameters[1]);
+ w_as_comma();
+ w_as_parameter (&next_instruction->instruction_parameters[1]);
+ w_as_newline();
+
+ return next_instruction;
+ } else if (next_instruction->instruction_parameters[1].parameter_data.reg.r==instruction->instruction_parameters[1].parameter_data.reg.r){
+ struct parameter parameter_0;
+
+ parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]);
+
+# ifdef FSUB_FDIV_REVERSED
+ if (next_instruction->instruction_parameters[1].parameter_flags)
+ w_as_opcode ("fnmsub");
+ else
+# endif
+ w_as_opcode ("fmsub");
+
+ w_as_parameter (&next_instruction->instruction_parameters[1]);
+ w_as_comma();
+ w_as_parameter (&parameter_0);
+ w_as_comma();
+ w_as_parameter (&instruction->instruction_parameters[1]);
+ w_as_comma();
+ w_as_parameter (&next_instruction->instruction_parameters[0]);
+ w_as_newline();
+
+ return next_instruction;
+ }
+ }
+ }
+
+ w_as_tryadic_float_instruction (instruction,"fmul");
+
+ return instruction;
+}
+#endif
+
+#ifdef FSUB_FDIV_REVERSED
+static void w_as_tryadic_reversed_float_instruction (struct instruction *instruction,char *opcode)
+{
+ struct parameter parameter_0;
+
+ parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]);
+
+ w_as_opcode (opcode);
+
+ w_as_parameter (&instruction->instruction_parameters[1]);
+ w_as_comma();
+ w_as_parameter (&parameter_0);
+ w_as_comma();
+ w_as_parameter (&instruction->instruction_parameters[1]);
+ w_as_newline();
+}
+#endif
+
+static struct instruction *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:
+ {
+ struct instruction *next_instruction;
+ int reg0,reg1;
+
+ reg0=instruction->instruction_parameters[0].parameter_data.reg.r;
+ reg1=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ next_instruction=instruction->instruction_next;
+ if (next_instruction)
+ switch (next_instruction->instruction_icode){
+ case IFADD: case IFSUB: case IFMUL: case IFDIV: case IFREM:
+ if (next_instruction->instruction_parameters[1].parameter_data.reg.r==reg1)
+ {
+ struct parameter parameter_0;
+ int reg_s;
+
+ parameter_0=w_as_float_parameter (next_instruction->instruction_parameters[0]);
+
+ reg_s=parameter_0.parameter_data.reg.r;
+ if (reg_s==reg1)
+ reg_s=reg0;
+
+ switch (next_instruction->instruction_icode){
+ case IFADD:
+ w_as_opcode ("fadd");
+ break;
+ case IFSUB:
+#ifdef FSUB_FDIV_REVERSED
+ if (instruction->instruction_parameters[1].parameter_flags){
+ int reg0_copy;
+
+ reg0_copy=reg0;
+ reg0=reg_s;
+ reg_s=reg0_copy;
+ }
+#endif
+
+ w_as_opcode ("fsub");
+ break;
+ case IFMUL:
+#ifdef FMADD
+ {
+ struct instruction *next_of_next_instruction;
+
+ next_of_next_instruction=next_instruction->instruction_next;
+ if (fmadd_flag && next_of_next_instruction!=NULL){
+ if (next_of_next_instruction->instruction_icode==IFADD &&
+ next_of_next_instruction->instruction_parameters[0].parameter_type==P_F_REGISTER &&
+ next_of_next_instruction->instruction_parameters[0].parameter_data.reg.r==reg1 &&
+ next_of_next_instruction->instruction_parameters[0].parameter_flags & FP_REG_LAST_USE &&
+ next_of_next_instruction->instruction_parameters[1].parameter_data.reg.r!=reg1)
+ {
+ w_as_opcode ("fmadd");
+
+ w_as_parameter (&next_of_next_instruction->instruction_parameters[1]);
+ w_as_comma();
+ w_as_fp_register (reg0);
+ w_as_comma();
+ w_as_fp_register (reg_s);
+ w_as_comma();
+ w_as_parameter (&next_of_next_instruction->instruction_parameters[1]);
+ w_as_newline();
+
+ return next_of_next_instruction;
+ } else if (next_of_next_instruction->instruction_icode==IFSUB &&
+ next_of_next_instruction->instruction_parameters[0].parameter_type==P_F_REGISTER &&
+ next_of_next_instruction->instruction_parameters[0].parameter_data.reg.r!=next_of_next_instruction->instruction_parameters[1].parameter_data.reg.r)
+ {
+ if (next_of_next_instruction->instruction_parameters[0].parameter_flags & FP_REG_LAST_USE &&
+ next_of_next_instruction->instruction_parameters[0].parameter_data.reg.r==reg1)
+ {
+# ifdef FSUB_FDIV_REVERSED
+ if (next_of_next_instruction->instruction_parameters[1].parameter_flags)
+ w_as_opcode ("fmsub");
+ else
+# endif
+ w_as_opcode ("fnmsub");
+
+ w_as_parameter (&next_of_next_instruction->instruction_parameters[1]);
+ w_as_comma();
+ w_as_fp_register (reg0);
+ w_as_comma();
+ w_as_fp_register (reg_s);
+ w_as_comma();
+ w_as_parameter (&next_of_next_instruction->instruction_parameters[1]);
+ w_as_newline();
+
+ return next_of_next_instruction;
+ } else if (next_of_next_instruction->instruction_parameters[1].parameter_data.reg.r==reg1){
+# ifdef FSUB_FDIV_REVERSED
+ if (next_of_next_instruction->instruction_parameters[1].parameter_flags)
+ w_as_opcode ("fnmsub");
+ else
+# endif
+ w_as_opcode ("fmsub");
+
+ w_as_parameter (&next_of_next_instruction->instruction_parameters[1]);
+ w_as_comma();
+ w_as_fp_register (reg0);
+ w_as_comma();
+ w_as_fp_register (reg_s);
+ w_as_comma();
+ w_as_parameter (&next_of_next_instruction->instruction_parameters[0]);
+ w_as_newline();
+
+ return next_of_next_instruction;
+ }
+ }
+ }
+ }
+#endif
+ w_as_opcode ("fmul");
+ break;
+ case IFDIV:
+#ifdef FSUB_FDIV_REVERSED
+ if (instruction->instruction_parameters[1].parameter_flags){
+ int reg0_copy;
+
+ reg0_copy=reg0;
+ reg0=reg_s;
+ reg_s=reg0_copy;
+ }
+#endif
+ w_as_opcode ("fdiv");
+ break;
+ case IFREM:
+ w_as_opcode ("frem");
+ }
+ w_as_fp_register (reg1);
+ w_as_comma();
+ w_as_fp_register (reg0);
+ w_as_comma();
+ w_as_fp_register (reg_s);
+ w_as_newline();
+
+ return next_instruction;
+ }
+ }
+
+ w_as_opcode ("fmr");
+ w_as_fp_register (reg1);
+ w_as_comma();
+ w_as_fp_register (reg0);
+ w_as_newline();
+
+ return instruction;
+ }
+ case P_INDIRECT:
+ w_as_opcode ("lfd");
+ w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_comma();
+ w_as_indirect (instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ w_as_newline();
+
+ return instruction;
+ case P_F_IMMEDIATE:
+ w_as_load_float_immediate (*instruction->instruction_parameters[0].parameter_data.r,instruction->instruction_parameters[1].parameter_data.reg.r);
+
+ return instruction;
+ case P_INDEXED:
+ w_as_opcode ("lfdx");
+ w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_comma();
+ w_as_indexed (instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.ir);
+ w_as_newline();
+
+ return instruction;
+ }
+ break;
+ case P_INDIRECT:
+ if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){
+ w_as_opcode ("stfd");
+ w_as_fp_register (instruction->instruction_parameters[0].parameter_data.reg.r);
+ w_as_comma();
+ w_as_indirect (instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_newline();
+
+ return instruction;
+ }
+ break;
+ case P_INDEXED:
+ if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){
+ w_as_opcode ("stfdx");
+ w_as_fp_register (instruction->instruction_parameters[0].parameter_data.reg.r);
+ w_as_comma();
+ w_as_indexed (instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.ir);
+ w_as_newline();
+
+ return instruction;
+ }
+ break;
+
+ }
+ internal_error_in_function ("w_as_fmove_instruction");
+ return instruction;
+}
+
+extern LABEL *r_to_i_buffer_label;
+
+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)
+ internal_error_in_function ("w_as_fmovel_instruction");
+
+ w_as_opcode ("fctiw");
+ w_as_fp_register (17);
+ w_as_comma();
+ w_as_fp_register (instruction->instruction_parameters[0].parameter_data.reg.r);
+ w_as_newline();
+
+ w_as_load_label (r_to_i_buffer_label,REGISTER_O0);
+
+ w_as_opcode ("stfd");
+ w_as_fp_register (17);
+ w_as_comma();
+ w_as_indirect (0,REGISTER_O0);
+ w_as_newline();
+
+ w_as_opcode ("lwz");
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_indirect (4,REGISTER_O0);
+ w_as_newline();
+ } else {
+ int reg;
+ int label_number,t_label_number;
+ struct label *new_label;
+
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_REGISTER:
+ reg=instruction->instruction_parameters[0].parameter_data.reg.r;
+ break;
+ case P_INDIRECT:
+ w_as_opcode ("lwz");
+ w_as_register_comma (REGISTER_O0);
+ w_as_indirect ( instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ w_as_newline();
+
+ reg=REGISTER_O0;
+ break;
+ case P_IMMEDIATE:
+ w_as_opcode ("li");
+ w_as_register_comma (REGISTER_O0);
+ w_as_immediate (instruction->instruction_parameters[0].parameter_data.i);
+ w_as_newline();
+
+ reg=REGISTER_O0;
+ break;
+ default:
+ internal_error_in_function ("w_as_fmovel_instruction");
+ }
+
+ label_number=next_label_id++;
+
+ new_label=(struct label*)allocate_memory_from_heap (sizeof (struct label));
+
+ new_label->label_flags=0;
+ new_label->label_number=label_number;
+
+ w_as_to_data_section();
+
+#ifdef GNU_SYNTAX
+ fprintf (assembly_file,"\t.align\t8" NEWLINE_STRING);
+#else
+ fprintf (assembly_file,"\talign\t3" NEWLINE_STRING);
+#endif
+/* w_as_define_internal_label (label_number); */
+ w_as_define_local_label (label_number);
+
+ fprintf (assembly_file,
+ "\t" DC_L "\t0x43300000" NEWLINE_STRING
+ "\t" DC_L "\t0x00000000" NEWLINE_STRING
+ "\t" DC_L "\t0x43300000" NEWLINE_STRING
+ "\t" DC_L "\t0x80000000" NEWLINE_STRING
+ );
+
+/*
+ w_as_instruction_without_parameters ("toc");
+
+ w_as_opcode ("tc");
+ fprintf (assembly_file,"t_%d{TC}",t_label_number);
+ w_as_comma();
+ w_as_internal_label (label_number);
+ w_as_newline();
+*/
+#ifndef GNU_SYNTAX
+ t_label_number=make_toc_label (new_label,0);
+#endif
+ w_as_to_code_section();
+
+ /*
+ lwz o1,t_n{TC}(RTOC)
+ xoris o0,reg,0x8000
+ lfd fp31,8(o1)
+ stw o0,4(o1)
+ lfd freg,0(o1)
+ fsub freg,freg,fp31
+ */
+#ifdef GNU_SYNTAX
+ load_label (new_label,0,REGISTER_O1);
+#else
+ w_as_opcode ("lwz");
+ w_as_register_comma (REGISTER_O1);
+ fprintf (assembly_file,"t_%d{TC}(RTOC)" NEWLINE_STRING,t_label_number);
+#endif
+ w_as_opcode ("xoris");
+ w_as_register_comma (REGISTER_O0);
+ w_as_register_comma (reg);
+ w_as_immediate (0x8000);
+ w_as_newline();
+
+ w_as_opcode ("lfd");
+ w_as_fp_register (17);
+ w_as_comma();
+ w_as_indirect (8,REGISTER_O1);
+ w_as_newline();
+
+ w_as_opcode ("stw");
+ w_as_register_comma (REGISTER_O0);
+ w_as_indirect (4,REGISTER_O1);
+ w_as_newline();
+
+ w_as_opcode ("lfd");
+ w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_comma();
+ w_as_indirect (0,REGISTER_O1);
+ w_as_newline();
+
+ w_as_opcode ("fsub");
+ w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_comma();
+ w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_comma();
+ w_as_fp_register (17);
+ w_as_newline();
+
+/* ++t_label_number; */
+ }
+}
+
+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_add_instruction (instruction);
+ break;
+ case IADDI:
+ w_as_i_instruction (instruction,"addi");
+ break;
+ case ISUB:
+ w_as_sub_instruction (instruction);
+ break;
+ case ICMP:
+ w_as_cmp_instruction (instruction,SIZE_LONG);
+ break;
+ case IJMP:
+ w_as_jmp_instruction (instruction);
+ break;
+ case IJSR:
+ w_as_jsr_instruction (instruction);
+ break;
+ case IRTS:
+ w_as_rts_instruction (instruction);
+ break;
+ case IBEQ:
+ w_as_branch_instruction (instruction,"beq");
+ break;
+ case IBGE:
+ w_as_branch_instruction (instruction,"bge");
+ break;
+ case IBGT:
+ w_as_branch_instruction (instruction,"bgt");
+ break;
+ case IBLE:
+ w_as_branch_instruction (instruction,"ble");
+ break;
+ case IBLT:
+ w_as_branch_instruction (instruction,"blt");
+ break;
+ case IBNE:
+ w_as_branch_instruction (instruction,"bne");
+ break;
+ case IBNEP:
+ w_as_branch_instruction (instruction,"bne+");
+ break;
+ case IBHS:
+ w_as_index_error_branch_instruction (instruction);
+ break;
+ case IBNO:
+ w_as_branchno_instruction (instruction);
+ break;
+ case IBO:
+ w_as_brancho_instruction (instruction);
+ break;
+ case ICMPLW:
+ w_as_cmplw_instruction (instruction);
+ break;
+ case ILSLI:
+ w_as_i_instruction (instruction,"slwi");
+ break;
+ case ILSL:
+ w_as_tryadic_instruction (instruction,"slw");
+ break;
+ case ILSR:
+ w_as_tryadic_instruction (instruction,"srw");
+ break;
+ case IASR:
+ w_as_tryadic_instruction (instruction,"sraw");
+ break;
+ case IMUL:
+ w_as_mul_instruction (instruction);
+ break;
+ case IDIV:
+ w_as_div_instruction (instruction);
+ break;
+ case IMOD:
+ w_as_rem_instruction (instruction);
+ break;
+ case IAND:
+ w_as_and_instruction (instruction);
+ break;
+ case IOR:
+ w_as_or_or_eor_instruction (instruction,"or");
+ break;
+ case IEOR:
+ w_as_or_or_eor_instruction (instruction,"xor");
+ break;
+ case ISEQ:
+ w_as_set_condition_instruction (instruction,"bne");
+ break;
+ case ISGE:
+ w_as_set_condition_instruction (instruction,"blt");
+ break;
+ case ISGT:
+ w_as_set_condition_instruction (instruction,"ble");
+ break;
+ case ISLE:
+ w_as_set_condition_instruction (instruction,"bgt");
+ break;
+ case ISLT:
+ w_as_set_condition_instruction (instruction,"bge");
+ break;
+ case ISNE:
+ w_as_set_condition_instruction (instruction,"beq");
+ break;
+ case ISNO:
+ w_as_setno_condition_instruction (instruction);
+ break;
+ case ISO:
+ w_as_seto_condition_instruction (instruction);
+ break;
+ case ICMPW:
+ w_as_cmp_instruction (instruction,SIZE_WORD);
+ break;
+ case ITST:
+ w_as_tst_instruction (instruction);
+ break;
+ case IBTST:
+ w_as_btst_instruction (instruction);
+ break;
+ case IMOVEW:
+ w_as_move_instruction (instruction,SIZE_WORD);
+ break;
+ case IMOVEB:
+ w_as_move_instruction (instruction,SIZE_BYTE);
+ break;
+ case IEXTB:
+ w_as_extb_instruction (instruction);
+ break;
+ case IFMOVE:
+ instruction=w_as_fmove_instruction (instruction);
+ break;
+ case IFADD:
+ w_as_tryadic_float_instruction (instruction,"fadd");
+ break;
+ case IFCMP:
+ w_as_compare_float_instruction (instruction);
+ break;
+ case IFDIV:
+#ifdef FSUB_FDIV_REVERSED
+ if (instruction->instruction_parameters[1].parameter_flags)
+ w_as_tryadic_reversed_float_instruction (instruction,"fdiv");
+ else
+#endif
+ w_as_tryadic_float_instruction (instruction,"fdiv");
+ break;
+ case IFMUL:
+#ifdef FMADD
+ instruction=w_as_fmul_instruction (instruction);
+#else
+ w_as_tryadic_float_instruction (instruction,"fmul");
+#endif
+ break;
+ case IFNEG:
+ w_as_dyadic_float_instruction (instruction,"fneg");
+ break;
+ case IFREM:
+ w_as_tryadic_float_instruction (instruction,"frem");
+ break;
+ case IFSUB:
+#ifdef FSUB_FDIV_REVERSED
+ if (instruction->instruction_parameters[1].parameter_flags)
+ w_as_tryadic_reversed_float_instruction (instruction,"fsub");
+ else
+#endif
+ w_as_tryadic_float_instruction (instruction,"fsub");
+ break;
+ case IFBEQ:
+ w_as_branch_instruction (instruction,"beq");
+ break;
+ case IFBGE:
+ w_as_branch_instruction (instruction,"bge");
+ break;
+ case IFBGT:
+ w_as_branch_instruction (instruction,"bgt");
+ break;
+ case IFBLE:
+ w_as_branch_instruction (instruction,"ble");
+ break;
+ case IFBLT:
+ w_as_branch_instruction (instruction,"blt");
+ break;
+ case IFBNE:
+ w_as_branch_instruction (instruction,"bne");
+ break;
+ case IFMOVEL:
+ w_as_fmovel_instruction (instruction);
+ break;
+ case IFSEQ:
+ w_as_set_condition_instruction (instruction,"bne");
+ break;
+ case IFSGE:
+ w_as_set_condition_instruction (instruction,"blt");
+ break;
+ case IFSGT:
+ w_as_set_condition_instruction (instruction,"ble");
+ break;
+ case IFSLE:
+ w_as_set_condition_instruction (instruction,"bgt");
+ break;
+ case IFSLT:
+ w_as_set_condition_instruction (instruction,"bge");
+ break;
+ case IFSNE:
+ w_as_set_condition_instruction (instruction,"beq");
+ break;
+ case IWORD:
+ w_as_word_instruction (instruction);
+ break;
+ case IMTCTR:
+ w_as_opcode ("mtctr");
+ w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r);
+ w_as_newline();
+ break;
+ case IJMPP:
+ w_as_jmpp_instruction (instruction);
+ break;
+ case IRTSP:
+ w_as_rtsp_instruction (instruction);
+ break;
+ case IADDO:
+ w_as_addo_instruction (instruction);
+ break;
+ case ISUBO:
+ w_as_subo_instruction (instruction);
+ break;
+ case IMULO:
+ w_as_mulo_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 (DC_L);
+ fprintf (assembly_file,"%d",n_node_arguments);
+ w_as_newline();
+}
+
+static void w_as_garbage_collect_test (register struct basic_block *block)
+{
+ LONG n_cells;
+ struct call_and_jump *new_call_and_jump;
+
+ n_cells= -block->block_n_new_heap_cells;
+
+ if (n_cells!=(WORD) n_cells){
+ w_as_opcode ("addis");
+ w_as_register_comma (REGISTER_D7);
+ w_as_register_comma (REGISTER_D7);
+ w_as_immediate ((n_cells-(WORD)n_cells)>>16);
+ w_as_newline();
+
+ n_cells=(WORD)n_cells;
+ }
+
+ w_as_opcode ("addic.");
+ w_as_register_comma (REGISTER_D7);
+ w_as_register_comma (REGISTER_D7);
+ w_as_immediate (n_cells);
+ w_as_newline();
+
+ new_call_and_jump=allocate_new_call_and_jump();
+
+ if (block->block_gc_kind!=0){
+ int label_id_1;
+
+ label_id_1=next_label_id++;
+
+ new_call_and_jump->cj_label_id=label_id_1;
+ new_call_and_jump->cj_jump_id=-1;
+
+ switch (block->block_n_begin_a_parameter_registers){
+ case 0: new_call_and_jump->cj_call_label_name="collect_00"; break;
+ case 1: new_call_and_jump->cj_call_label_name="collect_01"; break;
+ case 2: new_call_and_jump->cj_call_label_name="collect_02"; break;
+ case 3: new_call_and_jump->cj_call_label_name="collect_03"; break;
+ default: internal_error_in_function ("w_as_garbage_collect_test");
+ }
+
+ if (block->block_gc_kind==2){
+ w_as_opcode ("mflr");
+ w_as_register (REGISTER_R0);
+ w_as_newline();
+ }
+
+ w_as_opcode ("bltl-");
+ w_as_internal_label (label_id_1);
+ w_as_newline();
+
+ if (block->block_gc_kind==1){
+ w_as_opcode ("mtlr");
+ w_as_register (REGISTER_R0);
+ w_as_newline();
+ }
+ } else {
+ int label_id_1,label_id_2;
+
+ label_id_1=next_label_id++;
+ label_id_2=next_label_id++;
+
+ 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");
+ }
+
+ w_as_opcode ("blt");
+ w_as_internal_label (label_id_1);
+ w_as_newline ();
+
+ w_as_define_internal_label (label_id_2);
+ }
+}
+
+static void w_as_check_stack (struct basic_block *block)
+{
+#ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS
+ if (block->block_a_stack_check_size>0){
+ w_as_load_label (end_a_stack_label,REGISTER_O0);
+
+ w_as_opcode ("addi");
+ w_as_register_comma (REGISTER_O1);
+ w_as_register_comma (A_STACK_POINTER);
+ w_as_immediate (block->block_a_stack_check_size);
+ w_as_newline();
+
+ w_as_opcode ("lwz");
+ w_as_register_comma (REGISTER_O0);
+ w_as_indirect (0,REGISTER_O0);
+ w_as_newline();
+
+ w_as_opcode ("cmpw");
+ w_as_immediate (0);
+ w_as_comma();
+ w_as_register_comma (REGISTER_O1);
+ w_as_register (REGISTER_O0);
+ w_as_newline();
+
+ w_as_opcode ("ble+");
+ fprintf (assembly_file,".+8");
+ w_as_newline();
+
+ w_as_opcode ("b");
+ w_as_label (stack_overflow_label->label_name);
+ w_as_newline();
+ }
+ if (block->block_b_stack_check_size>0){
+ w_as_load_label (end_a_stack_label,REGISTER_O0);
+
+ w_as_opcode ("addi");
+ w_as_register_comma (REGISTER_O1);
+ w_as_register_comma (B_STACK_POINTER);
+ w_as_immediate (block->block_b_stack_check_size);
+ w_as_newline();
+
+ w_as_opcode ("lwz");
+ w_as_register_comma (REGISTER_O0);
+ w_as_indirect (0,REGISTER_O0);
+ w_as_newline();
+
+ w_as_opcode ("cmpw");
+ w_as_immediate (0);
+ w_as_comma();
+ w_as_register_comma (REGISTER_O1);
+ w_as_register (REGISTER_O0);
+ w_as_newline();
+
+ w_as_opcode ("bgt+");
+ fprintf (assembly_file,".+8");
+ w_as_newline();
+
+ w_as_opcode ("b");
+ w_as_label (stack_overflow_label->label_name);
+ w_as_newline();
+ }
+#else
+ int size;
+
+ size=block->block_stack_check_size+1024;
+
+ w_as_opcode ("sub");
+ w_as_register_comma (REGISTER_O0);
+ w_as_register_comma (B_STACK_POINTER);
+ w_as_register (A_STACK_POINTER);
+ w_as_newline();
+
+ w_as_opcode ("cmpwi");
+ w_as_register_comma (REGISTER_O0);
+ w_as_immediate (size);
+ w_as_newline();
+
+ w_as_opcode ("ble");
+ w_as_label (stack_overflow_label->label_name);
+ w_as_newline();
+#endif
+}
+
+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){
+ LABEL *label;
+
+ label=labels->block_label_label;
+
+ w_as_define_label (label);
+ } else
+ w_as_define_local_label (labels->block_label_label->label_number);
+}
+
+void initialize_write_assembly (FILE *ass_file)
+{
+ assembly_file=ass_file;
+
+ next_bmove_label=0;
+ in_data_section=0;
+
+ first_call_and_jump=NULL;
+#ifndef GNU_SYNTAX
+ fprintf (assembly_file,"\tstring\tasis" NEWLINE_STRING);
+#endif
+ data_module_number=0;
+ code_module_number=0;
+}
+
+static void w_as_import_labels (register struct label_node *label_node)
+{
+ LABEL *label;
+
+ if (label_node==NULL)
+ return;
+
+ label=&label_node->label_node_label;
+
+ if (!(label->label_flags & LOCAL_LABEL) && label->label_number==0){
+ w_as_opcode (IF_GNU (IF_MACH_O (".globl",".global"),"import"));
+#ifdef MACH_O
+ if (label->label_name[0]=='_'){
+ char *label_name;
+ int c;
+
+ label_name=label->label_name;
+ putc ('_',assembly_file);
+ ++label_name;
+ while (c=*label_name++,c!=0)
+ putc (c,assembly_file);
+
+ } else
+ w_as_label (label->label_name);
+#else
+ w_as_label (label->label_name);
+#endif
+ w_as_newline();
+ }
+
+ w_as_import_labels (label_node->label_node_left);
+ w_as_import_labels (label_node->label_node_right);
+}
+
+void write_assembly (VOID)
+{
+ struct basic_block *block;
+ struct call_and_jump *call_and_jump;
+ struct toc_label *toc_label;
+
+#ifdef MACH_O
+ first_stub=NULL;
+ next_stub_l=&first_stub;
+#endif
+
+ w_as_to_code_section();
+
+ w_as_import_labels (labels);
+
+ for_l (block,first_block,block_next){
+ if (block->block_begin_module && !block->block_link_module){
+ if (first_call_and_jump!=NULL){
+ struct call_and_jump *call_and_jump;
+
+ for_l (call_and_jump,first_call_and_jump,cj_next)
+ w_as_call_and_jump (call_and_jump);
+
+ first_call_and_jump=NULL;
+ }
+
+ w_as_new_code_module();
+ }
+
+ if (block->block_n_node_arguments>-100){
+ if (block->block_ea_label!=NULL){
+ int n_node_arguments;
+ extern LABEL *eval_fill_label,*eval_upd_labels[];
+
+ 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){
+ w_as_load_label (block->block_ea_label,REGISTER_A2);
+
+ if (!block->block_profile){
+ w_as_opcode ("b");
+ w_as_label (eval_upd_labels[n_node_arguments]->label_name);
+ w_as_newline();
+
+ w_as_instruction_without_parameters ("nop");
+#ifdef GNU_SYNTAX
+ w_as_instruction_without_parameters ("nop");
+#endif
+ } else {
+ if (profile_table_flag){
+ w_as_opcode ("b");
+ w_as_label (eval_upd_labels[n_node_arguments]->label_name);
+ fprintf (assembly_file,"-8");
+ w_as_newline();
+
+ w_as_load_label_with_offset (profile_table_label,32764,REGISTER_R3);
+
+ w_as_opcode ("addi");
+ w_as_register_comma (REGISTER_R3);
+ w_as_register_comma (REGISTER_R3);
+ w_as_immediate (block->block_profile_function_label->label_arity-32764);
+ w_as_newline();
+
+ w_as_opcode ("b");
+ fprintf (assembly_file,IF_GNU ("$-16","*-16"));
+ w_as_newline();
+ } else {
+ w_as_load_label (block->block_profile_function_label,REGISTER_R3);
+
+ w_as_opcode ("b");
+ w_as_label (eval_upd_labels[n_node_arguments]->label_name);
+ fprintf (assembly_file,"-8");
+ w_as_newline();
+ }
+ }
+ } else {
+ w_as_opcode ("b");
+ w_as_label (block->block_ea_label->label_name);
+ w_as_newline();
+
+ w_as_instruction_without_parameters ("nop");
+ w_as_instruction_without_parameters ("nop");
+#ifdef GNU_SYNTAX
+ w_as_instruction_without_parameters ("nop");
+ w_as_instruction_without_parameters ("nop");
+#endif
+ }
+
+ if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag || module_info_flag))
+#ifdef GNU_SYNTAX
+ w_as_label_in_code_section (block->block_descriptor->label_name);
+#else
+ w_as_load_label (block->block_descriptor,REGISTER_R0);
+#endif
+ else
+ w_as_number_of_arguments (0);
+ } else {
+ if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag || module_info_flag))
+#ifdef GNU_SYNTAX
+ w_as_label_in_code_section (block->block_descriptor->label_name);
+#else
+ w_as_load_label (block->block_descriptor,REGISTER_R0);
+#endif
+ /* else
+ w_as_number_of_arguments (0);
+ */
+ }
+ w_as_number_of_arguments (block->block_n_node_arguments);
+ }
+
+ w_as_labels (block->block_labels);
+
+ if (block->block_profile){
+ if (profile_table_flag){
+ w_as_load_label_with_offset (profile_table_label,32764,REGISTER_R3);
+
+ w_as_opcode ("mflr");
+ w_as_register (REGISTER_R0);
+ w_as_newline();
+
+ w_as_opcode ("addi");
+ w_as_register_comma (REGISTER_R3);
+ w_as_register_comma (REGISTER_R3);
+ w_as_immediate (block->block_profile_function_label->label_arity-32764);
+ w_as_newline();
+ } else {
+ w_as_load_label (block->block_profile_function_label,REGISTER_R3);
+
+ w_as_opcode ("mflr");
+ w_as_register (REGISTER_R0);
+ w_as_newline();
+ }
+
+ w_as_opcode ("bl");
+
+ 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();
+ }
+
+ if (block->block_n_new_heap_cells!=0)
+ w_as_garbage_collect_test (block);
+
+ if (check_stack
+#ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS
+ && (block->block_a_stack_check_size>0 || block->block_b_stack_check_size>0)
+#else
+ && block->block_stack_check_size>0
+#endif
+ )
+ 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);
+
+ *last_toc_next_p=NULL;
+
+#ifndef GNU_SYNTAX
+ w_as_instruction_without_parameters ("toc");
+
+ for_l (toc_label,toc_labels,toc_next)
+ w_as_toc_label (toc_label);
+#endif
+
+#ifdef MACH_O
+ write_stubs();
+#endif
+}
+
+#endif