summaryrefslogblamecommitdiff
path: root/cgpwas.c
blob: b6e34cbed909a6dfe2ad6b0ab9f65c96ee835164 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012








                                         
                   





































                              


                            
                                     
 
                                              
























































































































































































































































































































































                                                                                                                    
                  
































































































                                                                                       







                                                                     



















































































































































































































































































































































































































































































































                                                                                                                                
                         



                                                                          




                                                                                                          























                                                                                                                         






































































































































































                                                                                                          
                                                                  






                                                                                             
                                            
                    
                                             










































                                                                             
                                            






                                                                     






































































                                                                                             
                         











                                                                     















                                                                                 
      






















































































































































                                                                                                                         













                                                                                            















































































































































                                                                                                                          
             

                                                                         


















                                                                           





















                                                                 
                                                      


                                                  
                                                                 


                                                  
                                                   

                                     
                                                            



                                                                      






                                                                    







































                                                                                                            
                                                                    
                 

                                                  
                                                             

                                    
                                                      


                                                  
                                                             

                                     
                                                      


























































































































































































































                                                                                                                                                    















































                                                  

                                                                  
        


                                                                                


                                         



























































                                                                                                                                





































































                                                                                           




















































                                                                                           
                                                           
                                                                                           
                                                    
                               










                                                                                          











                                                                                          

















































                                                                                                       













                                                                                       





















































































                                                                                       
                                        




























                                                                                   
                                                    






                                                                                                  
                                                    












































































                                                                                                                                                                      
                                                                                                                                  
                                                                      
                                                                                                                             









                                                                                                                                                                                
                                                                                                                                  
                                                                      
                                                                                                                             



                                                                                                      

                                                                                                                                                                  
 
                                                                                                                  
 
                                                                                                                                     
 
                                                              
 



























                                                                                                                                                                                      










                                                                                                                                                                      
                                                                                                                                      
                                                                      















                                                                                                                                                                          
                                                                                                                                      
                                                                       











                                                                                                      



                                                                                                                                                                  
 
                                                                                                                                     
 













                                                                                                                                      
 
                                                                                                                  
 

















                                                                                                                                                                                      







                                                            













                                                                                                  
































                                                                                                                                                       
                                                                                                                                                                                  




                                                                                                                








                                                                                                                                                    














                                                                                                                                                                                                        




























                                                                                                                                                                                                                                                                                      





                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                      
                                                                                                                                              


                                                                                                                                                                                      
                                                                                                                                               



                                                                                                                                                                                                   
                                                                                                                                                                                                                      
                                                                                                                                               


                                                                                                                                                                                      
                                                                                                                                               










                                                                                                                                                                                      
                                                                                                                                                                                  




                                                                                                                



                                                                                                             
                                                                                                      






                                                                                                 
                                                                      





                                                                
                                                                                                                             









                                                                                                                                                                                         
                                                                                                                             








                                                                                                                            
                                                                                                                     








                                                                                                                        
                                                                                                                     




















                                                                                                                    
                                            




                                                                                               
                                            































































































                                                                                                                             
                                            







                                                  
                                                                                                     


                                              
                                                                                                     

























                                                                              
                                                                   



























































                                                                                  

                                                                    
                                  

































                                                                                   
     
                                   
                                                                    
                                      
      




                                                                    
                                     






                                                                              




                                                                   

                                                                                 

                                                                                   





                                                                                    
                                                                                                                         
                                                                                                     














                                                                                            
                                                                                                                         
                                                                                                     






























































                                                                                                            

                                                                     































































































































                                                                                                      
                                                                













































































































                                                                                          




























































































































































                                                                                                                            




























                                                                                 
                                                     
                 


                                                            

                                                  
                                                  
































                                                                                                   
/*
	File:      cgpwas.c
	Machine:   Power Macintosh
	Author:    John van Groningen
	Copyright: University of Nijmegen
*/

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.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"

#ifdef GNU_C
# include <ppc_intrinsics.h>
#endif

#define FP_REVERSE_SUB_DIV_OPERANDS 1

#define for_l(v,l,n) for(v=(l);v!=NULL;v=v->n)

#define IO_BUF_SIZE 8192

static FILE *assembly_file;

static void w_as_newline (VOID)
{
	putc (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 RTOC (-22)
#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_fp_register_comma (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,i2;

		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 if (((UWORD)i)==0){
			w_as_opcode ("andis.");
			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 (((unsigned int)i)>>16);
			w_as_newline();

			return;
		} else if (i2=i | (i-1),(i2 & (i2+1))==0){
			int n_leading_0_bits,n_leading_0_bits_and_1_bits;
			
			n_leading_0_bits = __cntlzw (i);
			n_leading_0_bits_and_1_bits = __cntlzw (i ^ ((unsigned)0xffffffffu>>(unsigned)n_leading_0_bits));
			
			w_as_opcode ("rlwinm");
			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 (0);
			w_as_comma();
			w_as_immediate (n_leading_0_bits);
			w_as_comma();
			w_as_immediate (n_leading_0_bits_and_1_bits-1);
			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)
{
	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 ("lwz");
		else
			w_as_opcode ("lwzx");

		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:
			w_as_opcode ("lwz");
			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:
			w_as_opcode ("lwzx");
			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();
}

#if 0
static void w_as_cmpw_instruction (struct instruction *instruction)
{
	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 ("lha");
		else
			w_as_opcode ("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:
			w_as_opcode ("lha");
			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:
			w_as_opcode ("lhax");
			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();
}
#endif

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");
	}
}

static void w_as_neg_instruction (struct instruction *instruction)
{
	w_as_opcode ("neg");
	w_as_register_comma (instruction->instruction_parameters[0].parameter_data.reg.r);
	w_as_register_newline (instruction->instruction_parameters[0].parameter_data.reg.r);
}

static void w_as_not_instruction (struct instruction *instruction)
{
	w_as_opcode ("nand");
	w_as_register_comma (instruction->instruction_parameters[0].parameter_data.reg.r);
	w_as_register_comma (instruction->instruction_parameters[0].parameter_data.reg.r);
	w_as_register_newline (instruction->instruction_parameters[0].parameter_data.reg.r);
}

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){
#ifdef MACH_O
			w_as_opcode ("mtctr");
			w_as_register (parameter0->parameter_data.reg.r);
			w_as_newline();
#else
			w_as_opcode ("lwz");
			w_as_register_comma (REGISTER_O1);
			w_as_indirect (0,parameter0->parameter_data.reg.r);
			w_as_newline();
			
			w_as_opcode ("stw");
			w_as_register_comma (RTOC);
			w_as_indirect (20-(frame_size+28),B_STACK_POINTER);
			w_as_newline();

			w_as_opcode ("lwz");
			w_as_register_comma (RTOC);
			w_as_indirect (4,parameter0->parameter_data.reg.r);
			w_as_newline();

			w_as_opcode ("mtctr");
			w_as_register (REGISTER_O1);
			w_as_newline();
#endif
		}

		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,B_STACK_POINTER);
		w_as_newline();

		w_as_opcode ("stwu");
		w_as_register_comma (REGISTER_O0);
		w_as_indirect (-(frame_size+28),B_STACK_POINTER);
		w_as_newline();		
#else
		w_as_opcode ("stw");
		w_as_register_comma (REGISTER_R0);
		w_as_indirect (-4,B_STACK_POINTER);
		w_as_newline();

		w_as_opcode ("stwu");
		w_as_register_comma (B_STACK_POINTER);
		w_as_indirect (-frame_size,B_STACK_POINTER);
		w_as_newline();
#endif
	
		if (parameter0->parameter_type==P_REGISTER){
			w_as_instruction_without_parameters ("bctrl");
#ifdef MACH_O
			w_as_instruction_without_parameters ("nop");
#else
			w_as_opcode ("lwz");
			w_as_register_comma (RTOC);
			w_as_indirect (20,B_STACK_POINTER);
			w_as_newline();
#endif
		} 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,B_STACK_POINTER);
		w_as_newline();

		w_as_opcode ("lwz");
		w_as_register_comma (B_STACK_POINTER);
		w_as_indirect (0,B_STACK_POINTER);
		w_as_newline();
#else
		w_as_opcode ("lwz");
		w_as_register_comma (REGISTER_R0);
		w_as_indirect (frame_size-4,B_STACK_POINTER);
		w_as_newline();

		w_as_opcode ("addi");
		w_as_register_comma (B_STACK_POINTER);
		w_as_register_comma (B_STACK_POINTER);
		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_divi (int i,int s_reg,int d_reg)
{
	struct ms ms;

	ms=magic (abs (i));
	
	w_as_opcode ("lis");
	w_as_register_comma (REGISTER_O0);
	w_as_immediate ((ms.m-(WORD)ms.m)>>16);
	w_as_newline();

	w_as_opcode ("addi");
	w_as_register_comma (REGISTER_O0);
	w_as_register_comma (REGISTER_O0);
	w_as_immediate ((WORD)ms.m);
	w_as_newline();

	w_as_opcode ("mulhw");
	w_as_register_comma (REGISTER_O0);
	w_as_register_comma (REGISTER_O0);
	w_as_register_newline (s_reg);

	if (ms.m<0){
		w_as_opcode ("add");
		w_as_register_comma (REGISTER_O0);
		w_as_register_comma (REGISTER_O0);
		w_as_register_newline (s_reg);
	}

	w_as_opcode (i>=0 ? "srwi" : "srawi");
	w_as_register_comma (d_reg);
	w_as_register_comma (s_reg);
	w_as_immediate (31);
	w_as_newline();

	if (ms.s>0){
		w_as_opcode ("srawi");
		w_as_register_comma (REGISTER_O0);
		w_as_register_comma (REGISTER_O0);
		w_as_immediate (ms.s);
		w_as_newline();
	}
				
	w_as_opcode (i>=0 ? "add" : "sub");
	w_as_register_comma (d_reg);
	w_as_register_comma (d_reg);
	w_as_register_newline (REGISTER_O0);
}

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<0 && i!=0x80000000)
			i=-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;
		} else if (i>1 || (i<-1 && i!=0x80000000)){
			int i2;
			
			sd_reg=instruction->instruction_parameters[1].parameter_data.reg.r;

			w_as_divi (i,sd_reg,REGISTER_O1);

			i2=i & (i-1);
			if ((i2 & (i2-1))==0){
				unsigned int n;
				int n_shifts;

				n=i;
				
				n_shifts=0;
				while (n>0){
					while ((n & 1)==0){
						n>>=1;
						++n_shifts;
					}
					
					if (n_shifts>0){
						w_as_opcode ("slwi");
						w_as_register_comma (REGISTER_O1);
						w_as_register_comma (REGISTER_O1);
						w_as_immediate (n_shifts);
						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);

					n>>=1;
					n_shifts=1;
				}
			} else {
				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();

					w_as_opcode ("mullw");
					w_as_register_comma (REGISTER_O1);
					w_as_register_comma (REGISTER_O1);
					w_as_register_newline (REGISTER_O0);
				} else {
					w_as_opcode ("mulli");
					w_as_register_comma (REGISTER_O1);
					w_as_register_comma (REGISTER_O1);
					w_as_immediate (i);
					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;
		} else if (i>1 || (i<-1 && i!=0x80000000)){
			sd_reg=instruction->instruction_parameters[1].parameter_data.reg.r;

			w_as_divi (i,sd_reg,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_divu_instruction (struct instruction *instruction)
{
	int reg;

	reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
	
	w_as_opcode ("divwu");
	
	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_umulh_instruction (struct instruction *instruction)
{
	int r,reg;
	
	r=instruction->instruction_parameters[1].parameter_data.reg.r;
	
	reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG);
	
	w_as_opcode ("mulhwu");	
	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_comma (fp_reg);
#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_comma (17);
			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_comma (17);
			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_fp_register_comma (next_instruction->instruction_parameters[1].parameter_data.reg.r);
					w_as_parameter (&parameter_0);
					w_as_comma();
					w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
					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_fp_register_comma (next_instruction->instruction_parameters[1].parameter_data.reg.r);
					w_as_parameter (&parameter_0);
					w_as_comma();
					w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
					w_as_parameter (&next_instruction->instruction_parameters[0]);
					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){
				if (next_instruction->instruction_parameters[0].parameter_type==P_F_IMMEDIATE){
					struct parameter parameter_0;

					parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]);

					w_as_load_float_immediate (*next_instruction->instruction_parameters[0].parameter_data.r,16);

					w_as_opcode ("fmadd");

					w_as_fp_register_comma (next_instruction->instruction_parameters[1].parameter_data.reg.r);
					w_as_parameter (&parameter_0);
					w_as_comma();
					w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
					w_as_fp_register (16);
					w_as_newline();
					
					return next_instruction;
				} else if (	next_instruction->instruction_parameters[0].parameter_type==P_INDIRECT){
					struct parameter parameter_0;

					parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]);

					w_as_opcode ("lfd");
					w_as_fp_register_comma (16);
					w_as_indirect (next_instruction->instruction_parameters[0].parameter_offset,next_instruction->instruction_parameters[0].parameter_data.reg.r);
					w_as_newline();

					w_as_opcode ("fmadd");

					w_as_fp_register_comma (next_instruction->instruction_parameters[1].parameter_data.reg.r);
					w_as_parameter (&parameter_0);
					w_as_comma();
					w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
					w_as_fp_register (16);
					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]);
					
					if (next_instruction->instruction_parameters[1].parameter_flags & FP_REVERSE_SUB_DIV_OPERANDS)
						w_as_opcode ("fmsub");
					else
						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]);
					
					if (next_instruction->instruction_parameters[1].parameter_flags & FP_REVERSE_SUB_DIV_OPERANDS)
						w_as_opcode ("fnmsub");
					else
						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;
				}
			} else if (next_instruction->instruction_parameters[1].parameter_data.reg.r==instruction->instruction_parameters[1].parameter_data.reg.r){
				if (next_instruction->instruction_parameters[0].parameter_type==P_F_IMMEDIATE){
					struct parameter parameter_0;

					parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]);

					w_as_load_float_immediate (*next_instruction->instruction_parameters[0].parameter_data.r,16);

					if (next_instruction->instruction_parameters[1].parameter_flags & FP_REVERSE_SUB_DIV_OPERANDS)
						w_as_opcode ("fnmsub");
					else
						w_as_opcode ("fmsub");

					w_as_fp_register_comma (next_instruction->instruction_parameters[1].parameter_data.reg.r);
					w_as_parameter (&parameter_0);
					w_as_comma();
					w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
					w_as_fp_register (16);
					w_as_newline();
					
					return next_instruction;
				} else if (next_instruction->instruction_parameters[0].parameter_type==P_INDIRECT){
					struct parameter parameter_0;

					parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]);

					w_as_opcode ("lfd");
					w_as_fp_register_comma (16);
					w_as_indirect (next_instruction->instruction_parameters[0].parameter_offset,next_instruction->instruction_parameters[0].parameter_data.reg.r);
					w_as_newline();

					if (next_instruction->instruction_parameters[1].parameter_flags & FP_REVERSE_SUB_DIV_OPERANDS)
						w_as_opcode ("fnmsub");
					else
						w_as_opcode ("fmsub");

					w_as_fp_register_comma (next_instruction->instruction_parameters[1].parameter_data.reg.r);
					w_as_parameter (&parameter_0);
					w_as_comma();
					w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
					w_as_fp_register (16);
					w_as_newline();
					
					return next_instruction;
				}
			}
		}

	w_as_tryadic_float_instruction (instruction,"fmul");

	return instruction;
}
#endif

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();
}

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:
											if (instruction->instruction_parameters[1].parameter_flags & FP_REVERSE_SUB_DIV_OPERANDS){
												int reg0_copy;
												
												reg0_copy=reg0;
												reg0=reg_s;
												reg_s=reg0_copy;
											}

											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){
													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)
													{
														w_as_opcode ("fmadd");

														w_as_parameter (&next_of_next_instruction->instruction_parameters[1]);
														w_as_comma();
														w_as_fp_register_comma (reg0);
														w_as_fp_register_comma (reg_s);
														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){
														if (next_of_next_instruction->instruction_parameters[0].parameter_type==P_F_IMMEDIATE){
															w_as_load_float_immediate (*next_of_next_instruction->instruction_parameters[0].parameter_data.r,16);
															
															w_as_opcode ("fmadd");

															w_as_fp_register_comma (reg1);
															w_as_fp_register_comma (reg0);
															w_as_fp_register_comma (reg_s);
															w_as_fp_register (16);
															w_as_newline();
															
															return next_of_next_instruction;
														} else if (	next_of_next_instruction->instruction_parameters[0].parameter_type==P_INDIRECT){
															w_as_opcode ("lfd");
															w_as_fp_register_comma (16);
															w_as_indirect (next_of_next_instruction->instruction_parameters[0].parameter_offset,next_of_next_instruction->instruction_parameters[0].parameter_data.reg.r);
															w_as_newline();
															
															w_as_opcode ("fmadd");

															w_as_fp_register_comma (reg1);
															w_as_fp_register_comma (reg0);
															w_as_fp_register_comma (reg_s);
															w_as_fp_register (16);
															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)
													{
														if (next_of_next_instruction->instruction_parameters[1].parameter_flags & FP_REVERSE_SUB_DIV_OPERANDS)
															w_as_opcode ("fmsub");
														else
															w_as_opcode ("fnmsub");

														w_as_parameter (&next_of_next_instruction->instruction_parameters[1]);
														w_as_comma();
														w_as_fp_register_comma (reg0);
														w_as_fp_register_comma (reg_s);
														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){
														if (next_of_next_instruction->instruction_parameters[1].parameter_flags & FP_REVERSE_SUB_DIV_OPERANDS)
															w_as_opcode ("fnmsub");
														else
															w_as_opcode ("fmsub");

														w_as_parameter (&next_of_next_instruction->instruction_parameters[1]);
														w_as_comma();
														w_as_fp_register_comma (reg0);
														w_as_fp_register_comma (reg_s);
														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:
											if (instruction->instruction_parameters[1].parameter_flags & FP_REVERSE_SUB_DIV_OPERANDS){
												int reg0_copy;
												
												reg0_copy=reg0;
												reg0=reg_s;
												reg_s=reg0_copy;
											}
											w_as_opcode ("fdiv");
											break;
										case IFREM:
											w_as_opcode ("frem");
									}
									w_as_fp_register_comma (reg1);
									w_as_fp_register_comma (reg0);
									w_as_fp_register (reg_s);
									w_as_newline();
									
									return next_instruction;
								}
						}

					w_as_opcode ("fmr");
					w_as_fp_register_comma (reg1);
					w_as_fp_register (reg0);
					w_as_newline();
				
					return instruction;
				}
				case P_INDIRECT:
					w_as_opcode ("lfd");
					w_as_fp_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 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_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 instruction;
			}
			break;
		case P_INDIRECT:
			if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){
				w_as_opcode ("stfd");
				w_as_fp_register_comma (instruction->instruction_parameters[0].parameter_data.reg.r);
				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_comma (instruction->instruction_parameters[0].parameter_data.reg.r);
				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_comma (17);
		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_comma (17);
		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_comma (17);
		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_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
		w_as_indirect (0,REGISTER_O1);
		w_as_newline();

		w_as_opcode ("fsub");
		w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
		w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
		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);
				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 IDIVU:
				w_as_divu_instruction (instruction);
				break;
			case IREM:
				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;
#if 0
			case ICMPW:
				w_as_cmpw_instruction (instruction);
				break;
#endif
			case ITST:
				w_as_tst_instruction (instruction);
				break;
			case IBTST:
				w_as_btst_instruction (instruction);
				break;
			case IMOVEDB:
				w_as_move_instruction (instruction,SIZE_WORD);
				break;
			case IMOVEB:
				w_as_move_instruction (instruction,SIZE_BYTE);
				break;
			case IEXTB:
				w_as_extb_instruction (instruction);
				break;
			case INEG:
				w_as_neg_instruction (instruction);
				break;
			case INOT:
				w_as_not_instruction (instruction);
				break;
			case IFMOVE:
				instruction=w_as_fmove_instruction (instruction);
				break;
			case IFABS:
				w_as_dyadic_float_instruction (instruction,"fabs");
				break;				
			case IFADD:
				w_as_tryadic_float_instruction (instruction,"fadd");
				break;
			case IFCMP:
				w_as_compare_float_instruction (instruction);
				break;
			case IFDIV:
				if (instruction->instruction_parameters[1].parameter_flags & FP_REVERSE_SUB_DIV_OPERANDS)
					w_as_tryadic_reversed_float_instruction (instruction,"fdiv");
				else
					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:
				if (instruction->instruction_parameters[1].parameter_flags & FP_REVERSE_SUB_DIV_OPERANDS)
					w_as_tryadic_reversed_float_instruction (instruction,"fsub");
				else
					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 IUMULH:
				w_as_umulh_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_b_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);
}

static void w_as_node_entry_info (struct basic_block *block)
{
	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);
}

static void w_as_profile_call (struct basic_block *block)
{
	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();
}

#ifdef NEW_APPLY
extern LABEL *add_empty_node_labels[];

static void w_as_apply_update_entry (struct basic_block *block)
{
	if (block->block_profile)
		w_as_profile_call (block);

	if (block->block_n_node_arguments==-200){
		w_as_opcode ("b");
		w_as_label (block->block_ea_label->label_name);
		w_as_newline();

		w_as_instruction_without_parameters ("nop");
		w_as_instruction_without_parameters ("nop");
		w_as_instruction_without_parameters ("nop");
	} else {
		w_as_opcode ("mflr");
		w_as_register (REGISTER_R0);
		w_as_newline();

		w_as_opcode ("bl");
		w_as_label (add_empty_node_labels[block->block_n_node_arguments+200]->label_name);
		w_as_newline();

		w_as_opcode ("mtlr");
		w_as_register (REGISTER_R0);
		w_as_newline();

		w_as_opcode ("b");
		w_as_label (block->block_ea_label->label_name);
		w_as_newline();
	}
}
#endif

void write_assembly (VOID)
{
	struct basic_block *block;
	struct call_and_jump *call_and_jump;
	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){
			w_as_node_entry_info (block);
		}
#ifdef NEW_APPLY
		else if (block->block_n_node_arguments<-100)
			w_as_apply_update_entry (block);
#endif

		w_as_labels (block->block_labels);

		if (block->block_profile)
			w_as_profile_call (block);

		if (block->block_n_new_heap_cells!=0)
			w_as_garbage_collect_test (block);
		
		if (check_stack
#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