mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-10-26 16:33:45 +01:00 
			
		
		
		
	* more MIPS code of David Zhang integrated
git-svn-id: trunk@14228 -
This commit is contained in:
		
							parent
							
								
									2ef18ba527
								
							
						
					
					
						commit
						0c8546f94c
					
				
							
								
								
									
										14
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							| @ -234,15 +234,21 @@ compiler/m68k/ra68k.pas svneol=native#text/plain | ||||
| compiler/m68k/ra68kmot.pas svneol=native#text/plain | ||||
| compiler/m68k/rgcpu.pas svneol=native#text/plain | ||||
| compiler/mips/aasmcpu.pas svneol=native#text/plain | ||||
| compiler/mips/cgcpu.pas svneol=native#text/pascal | ||||
| compiler/mips/aoptcpu.pas svneol=native#text/plain | ||||
| compiler/mips/aoptcpub.pas svneol=native#text/plain | ||||
| compiler/mips/aoptcpud.pas svneol=native#text/plain | ||||
| compiler/mips/cgcpu.pas svneol=native#text/plain | ||||
| compiler/mips/cpubase.pas svneol=native#text/plain | ||||
| compiler/mips/cpugas.pas svneol=native#text/plain | ||||
| compiler/mips/cpuinfo.pas svneol=native#text/plain | ||||
| compiler/mips/cpupara.pas svneol=native#text/pascal | ||||
| compiler/mips/cpupi.pas svneol=native#text/pascal | ||||
| compiler/mips/cpunode.pas svneol=native#text/plain | ||||
| compiler/mips/cpupara.pas svneol=native#text/plain | ||||
| compiler/mips/cpupi.pas svneol=native#text/plain | ||||
| compiler/mips/itcpugas.pas svneol=native#text/plain | ||||
| compiler/mips/mipsreg.dat svneol=native#text/plain | ||||
| compiler/mips/ncpuadd.pas svneol=native#text/plain | ||||
| compiler/mips/opcode.inc svneol=native#text/plain | ||||
| compiler/mips/rgcpu.pas svneol=native#text/pascal | ||||
| compiler/mips/rgcpu.pas svneol=native#text/plain | ||||
| compiler/mips/rmipscon.inc svneol=native#text/plain | ||||
| compiler/mips/rmipsdwf.inc svneol=native#text/plain | ||||
| compiler/mips/rmipsgas.inc svneol=native#text/plain | ||||
|  | ||||
| @ -3067,7 +3067,7 @@ unit cgcpu; | ||||
|               begin | ||||
|                 { restore int registers and return } | ||||
|                 list.concat(taicpu.op_reg_reg(A_MOV, NR_STACK_POINTER_REG, NR_R11)); | ||||
|                  | ||||
| 
 | ||||
|                 reference_reset(ref,4); | ||||
|                 ref.index:=NR_STACK_POINTER_REG; | ||||
|                 list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,regs),PF_DB)); | ||||
| @ -3195,7 +3195,7 @@ unit cgcpu; | ||||
|             tmpreg:=getintregister(list,OS_ADDR); | ||||
| 
 | ||||
|             list.concat(taicpu.op_reg_reg(A_MOV, tmpreg, NR_R15)); | ||||
|          | ||||
| 
 | ||||
|             ref.base := tmpreg; | ||||
|           end; | ||||
| 
 | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| { | ||||
|     Copyright (c) 2003 by Florian Klaempfl | ||||
|     Copyright (c) 1999-2009 by Mazen Neifer and David Zhang | ||||
| 
 | ||||
|     Contains the assembler object for MIPS | ||||
|     Contains the assembler object for the MIPSEL | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
| @ -26,314 +26,424 @@ unit aasmcpu; | ||||
| interface | ||||
| 
 | ||||
| uses | ||||
|   cclasses,aasmtai,aasmdata, | ||||
|   aasmbase,globtype,globals,verbose, | ||||
|   cpubase,cpuinfo,cgbase,cgutils; | ||||
|   cclasses, | ||||
|   globtype, globals, verbose, | ||||
|   aasmbase, aasmtai, | ||||
|   cgbase, cgutils, cpubase, cpuinfo; | ||||
| 
 | ||||
|     const | ||||
|       { "mov reg,reg" source operand number } | ||||
|       O_MOV_SOURCE = 1; | ||||
|       { "mov reg,reg" source operand number } | ||||
|       O_MOV_DEST = 0; | ||||
| const | ||||
|   { "mov reg,reg" source operand number } | ||||
|   O_MOV_SOURCE = 0; | ||||
|   { "mov reg,reg" source operand number } | ||||
|   O_MOV_DEST   = 1; | ||||
| 
 | ||||
|     type | ||||
|       taicpu = class(tai_cpu_abstract) | ||||
|          constructor op_none(op : tasmop); | ||||
| type | ||||
|   taicpu = class(tai_cpu_abstract) | ||||
|     delayslot_annulled: boolean;   { conditinal opcode with ,a } | ||||
|     constructor op_none(op: tasmop); | ||||
| 
 | ||||
|          constructor op_reg(op : tasmop;_op1 : tregister); | ||||
|          constructor op_const(op : tasmop;_op1 : longint); | ||||
|     constructor op_reg(op: tasmop; _op1: tregister); | ||||
|     constructor op_const(op: tasmop; _op1: longint); | ||||
|     constructor op_ref(op: tasmop; const _op1: treference); | ||||
| 
 | ||||
|          constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister); | ||||
|          constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference); | ||||
|          constructor op_reg_const(op:tasmop; _op1: tregister; _op2: aint); | ||||
|     constructor op_reg_reg(op: tasmop; _op1, _op2: tregister); | ||||
|     constructor op_reg_ref(op: tasmop; _op1: tregister; const _op2: treference); | ||||
|     constructor op_reg_const(op: tasmop; _op1: tregister; _op2: longint); | ||||
| 
 | ||||
|          constructor op_ref_regset(op:tasmop; _op1: treference; _op2: tcpuregisterset); | ||||
|     constructor op_reg_reg_reg(op: tasmop; _op1, _op2, _op3: tregister); | ||||
| 
 | ||||
|          constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister); | ||||
|          constructor op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint); | ||||
|          constructor op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint); | ||||
|          constructor op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference); | ||||
|          { SFM/LFM } | ||||
|          constructor op_reg_const_ref(op : tasmop;_op1 : tregister;_op2 : aint;_op3 : treference); | ||||
|     constructor op_reg_reg_ref(op: tasmop; _op1, _op2: tregister; const _op3: treference); | ||||
|     constructor op_reg_reg_const(op: tasmop; _op1, _op2: tregister; _op3: aint); | ||||
| 
 | ||||
|          { this is for Jmp instructions } | ||||
|          constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol); | ||||
|     { this is for Jmp instructions } | ||||
|     constructor op_sym(op: tasmop; _op1: tasmsymbol); | ||||
|     constructor op_reg_reg_sym(op: tasmop; _op1, _op2: tregister; _op3: tasmsymbol); | ||||
|     constructor op_reg_sym(op: tasmop; _op1: tregister; _op2: tasmsymbol); | ||||
|     constructor op_sym_ofs(op: tasmop; _op1: tasmsymbol; _op1ofs: longint); | ||||
| 
 | ||||
|          constructor op_sym(op : tasmop;_op1 : tasmsymbol); | ||||
|          constructor op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint); | ||||
|          constructor op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint); | ||||
|          constructor op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference); | ||||
|     { register allocation } | ||||
|     function is_same_reg_move(regtype: Tregistertype): boolean; override; | ||||
| 
 | ||||
|          function is_same_reg_move(regtype: Tregistertype):boolean; override; | ||||
|     { register spilling code } | ||||
|     function spilling_get_operation_type(opnr: longint): topertype; override; | ||||
|   end; | ||||
| 
 | ||||
|          function spilling_get_operation_type(opnr: longint): topertype;override; | ||||
|       end; | ||||
|       tai_align = class(tai_align_abstract) | ||||
|         { nothing to add } | ||||
|       end; | ||||
|   tai_align = class(tai_align_abstract) | ||||
|     { nothing to add } | ||||
|   end; | ||||
| 
 | ||||
|     function spilling_create_load(const ref:treference;r:tregister): tai; | ||||
|     function spilling_create_store(r:tregister; const ref:treference): tai; | ||||
| 
 | ||||
|     procedure InitAsm; | ||||
|     procedure DoneAsm; | ||||
|   procedure InitAsm; | ||||
|   procedure DoneAsm; | ||||
| 
 | ||||
|   function spilling_create_load(const ref: treference; r: tregister): taicpu; | ||||
|   function spilling_create_store(r: tregister; const ref: treference): taicpu; | ||||
| 
 | ||||
| implementation | ||||
| 
 | ||||
|   uses | ||||
|     cutils,rgobj,itcpugas; | ||||
| 
 | ||||
| 
 | ||||
| {***************************************************************************** | ||||
|                                  taicpu Constructors | ||||
| *****************************************************************************} | ||||
| 
 | ||||
|     constructor taicpu.op_none(op : tasmop); | ||||
|       begin | ||||
|          inherited create(op); | ||||
|       end; | ||||
| 
 | ||||
| 
 | ||||
|     constructor taicpu.op_reg(op : tasmop;_op1 : tregister); | ||||
|       begin | ||||
|          inherited create(op); | ||||
|          ops:=1; | ||||
|          loadreg(0,_op1); | ||||
|       end; | ||||
| constructor taicpu.op_none(op: tasmop); | ||||
| begin | ||||
|   inherited Create(op); | ||||
| end; | ||||
| 
 | ||||
| 
 | ||||
|     constructor taicpu.op_const(op : tasmop;_op1 : longint); | ||||
|       begin | ||||
|          inherited create(op); | ||||
|          ops:=1; | ||||
|          loadconst(0,aint(_op1)); | ||||
|       end; | ||||
| constructor taicpu.op_reg(op: tasmop; _op1: tregister); | ||||
| begin | ||||
|   inherited Create(op); | ||||
|   ops := 1; | ||||
|   loadreg(0, _op1); | ||||
| end; | ||||
| 
 | ||||
| 
 | ||||
|     constructor taicpu.op_reg_reg(op : tasmop;_op1,_op2 : tregister); | ||||
|       begin | ||||
|          inherited create(op); | ||||
|          ops:=2; | ||||
|          loadreg(0,_op1); | ||||
|          loadreg(1,_op2); | ||||
|       end; | ||||
| constructor taicpu.op_ref(op: tasmop; const _op1: treference); | ||||
| begin | ||||
|   inherited Create(op); | ||||
|   ops := 1; | ||||
|   loadref(0, _op1); | ||||
| end; | ||||
| 
 | ||||
| 
 | ||||
|     constructor taicpu.op_reg_const(op:tasmop; _op1: tregister; _op2: aint); | ||||
|       begin | ||||
|          inherited create(op); | ||||
|          ops:=2; | ||||
|          loadreg(0,_op1); | ||||
|          loadconst(1,aint(_op2)); | ||||
|       end; | ||||
| constructor taicpu.op_const(op: tasmop; _op1: longint); | ||||
| begin | ||||
|   inherited Create(op); | ||||
|   ops := 1; | ||||
|   loadconst(0, _op1); | ||||
| end; | ||||
| 
 | ||||
| 
 | ||||
|     constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference); | ||||
|       begin | ||||
|          inherited create(op); | ||||
|          ops:=2; | ||||
|          loadreg(0,_op1); | ||||
|          loadref(1,_op2); | ||||
|       end; | ||||
| constructor taicpu.op_reg_reg(op: tasmop; _op1, _op2: tregister); | ||||
| begin | ||||
|   inherited Create(op); | ||||
|   ops := 2; | ||||
|   loadreg(0, _op1); | ||||
|   loadreg(1, _op2); | ||||
| end; | ||||
| 
 | ||||
| constructor taicpu.op_reg_const(op: tasmop; _op1: tregister; _op2: longint); | ||||
| begin | ||||
|   inherited Create(op); | ||||
|   ops := 2; | ||||
|   loadreg(0, _op1); | ||||
|   loadconst(1, _op2); | ||||
| end; | ||||
| 
 | ||||
| 
 | ||||
|     constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister); | ||||
|       begin | ||||
|          inherited create(op); | ||||
|          ops:=3; | ||||
|          loadreg(0,_op1); | ||||
|          loadreg(1,_op2); | ||||
|          loadreg(2,_op3); | ||||
|       end; | ||||
| constructor taicpu.op_reg_ref(op: tasmop; _op1: tregister; const _op2: treference); | ||||
| begin | ||||
|   inherited Create(op); | ||||
|   ops := 2; | ||||
|   loadreg(0, _op1); | ||||
|   loadref(1, _op2); | ||||
| end; | ||||
| 
 | ||||
| 
 | ||||
|      constructor taicpu.op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint); | ||||
|        begin | ||||
|          inherited create(op); | ||||
|          ops:=3; | ||||
|          loadreg(0,_op1); | ||||
|          loadreg(1,_op2); | ||||
|          loadconst(2,aint(_op3)); | ||||
|       end; | ||||
| constructor taicpu.op_reg_reg_reg(op: tasmop; _op1, _op2, _op3: tregister); | ||||
| begin | ||||
|   inherited Create(op); | ||||
|   ops := 3; | ||||
|   loadreg(0, _op1); | ||||
|   loadreg(1, _op2); | ||||
|   loadreg(2, _op3); | ||||
| end; | ||||
| 
 | ||||
| 
 | ||||
|     constructor taicpu.op_reg_const_ref(op : tasmop;_op1 : tregister;_op2 : aint;_op3 : treference); | ||||
|       begin | ||||
|          inherited create(op); | ||||
|          ops:=3; | ||||
|          loadreg(0,_op1); | ||||
|          loadconst(1,_op2); | ||||
|          loadref(2,_op3); | ||||
|       end; | ||||
| constructor taicpu.op_reg_reg_ref(op: tasmop; _op1, _op2: tregister; const _op3: treference); | ||||
|  begin | ||||
|    inherited create(op); | ||||
|    ops := 3; | ||||
|    loadreg(0, _op1); | ||||
|    loadreg(1, _op2); | ||||
|    loadref(2, _op3); | ||||
| end; | ||||
| 
 | ||||
| constructor taicpu.op_reg_reg_const(op: tasmop; _op1, _op2: tregister; _op3: aint); | ||||
|  begin | ||||
|    inherited create(op); | ||||
|    ops := 3; | ||||
|    loadreg(0, _op1); | ||||
|    loadreg(1, _op2); | ||||
|    loadconst(2, _op3); | ||||
| end; | ||||
| 
 | ||||
| 
 | ||||
|      constructor taicpu.op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint); | ||||
|        begin | ||||
|          inherited create(op); | ||||
|          ops:=3; | ||||
|          loadreg(0,_op1); | ||||
|          loadreg(1,_op2); | ||||
|          loadsymbol(0,_op3,_op3ofs); | ||||
|       end; | ||||
| 
 | ||||
| constructor taicpu.op_sym(op: tasmop; _op1: tasmsymbol); | ||||
| begin | ||||
|   inherited Create(op); | ||||
|   is_jmp := op in [A_J, A_BEQI, A_BNEI, A_BLTI, A_BLEI, A_BGTI, A_BGEI, | ||||
|     A_BLTUI, A_BLEUI, A_BGTUI, A_BGEUI, | ||||
|     A_BEQ, A_BNE, A_BLT, A_BLE, A_BGT, A_BGE, | ||||
|     A_BLTU, A_BLEU, A_BGTU, A_BGEU | ||||
|     ]; | ||||
| 
 | ||||
|   ops := 1; | ||||
|   loadsymbol(0, _op1, 0); | ||||
| end; | ||||
| 
 | ||||
| constructor taicpu.op_reg_reg_sym(op: tasmop; _op1, _op2: tregister; _op3: tasmsymbol); | ||||
| begin | ||||
|    inherited create(op); | ||||
|    is_jmp := op in [A_J, | ||||
|      A_BEQI, A_BNEI, A_BLTI, A_BLEI, A_BGTI, A_BGEI, A_BLTUI, A_BLEUI, | ||||
|      A_BGTUI, A_BGEUI, | ||||
|      A_BEQ, A_BNE, A_BLT, A_BLE, A_BGT, A_BGE, A_BLTU, A_BLEU, A_BGTU, A_BGEU]; | ||||
|    ops := 3; | ||||
|    loadreg(0, _op1); | ||||
|    loadreg(1, _op2); | ||||
|    loadsymbol(2, _op3, 0); | ||||
| end; | ||||
| 
 | ||||
| constructor taicpu.op_reg_sym(op: tasmop; _op1: tregister; _op2: tasmsymbol); | ||||
| begin | ||||
|    inherited create(op); | ||||
|    is_jmp := op in [A_J, | ||||
|      A_BEQI, A_BNEI, A_BLTI, A_BLEI, A_BGTI, A_BGEI, A_BLTUI, A_BLEUI, | ||||
|      A_BGTUI, A_BGEUI, | ||||
|      A_BEQ, A_BNE, A_BLT, A_BLE, A_BGT, A_BGE, A_BLTU, A_BLEU, A_BGTU, A_BGEU, A_BGTZ]; | ||||
|    ops := 2; | ||||
|    loadreg(0, _op1); | ||||
|    loadsymbol(1, _op2, 0); | ||||
| end; | ||||
| 
 | ||||
| constructor taicpu.op_sym_ofs(op: tasmop; _op1: tasmsymbol; _op1ofs: longint); | ||||
| begin | ||||
|   inherited Create(op); | ||||
|   ops := 1; | ||||
|   loadsymbol(0, _op1, _op1ofs); | ||||
| end; | ||||
| 
 | ||||
| 
 | ||||
|      constructor taicpu.op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference); | ||||
|        begin | ||||
|          inherited create(op); | ||||
|          ops:=3; | ||||
|          loadreg(0,_op1); | ||||
|          loadreg(1,_op2); | ||||
|          loadref(2,_op3); | ||||
|       end; | ||||
| 
 | ||||
| 
 | ||||
|     constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol); | ||||
|       begin | ||||
|          inherited create(op); | ||||
|          condition:=cond; | ||||
|          ops:=1; | ||||
|          loadsymbol(0,_op1,0); | ||||
|       end; | ||||
| 
 | ||||
| 
 | ||||
|     constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol); | ||||
|       begin | ||||
|          inherited create(op); | ||||
|          ops:=1; | ||||
|          loadsymbol(0,_op1,0); | ||||
|       end; | ||||
| 
 | ||||
| 
 | ||||
|     constructor taicpu.op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint); | ||||
|       begin | ||||
|          inherited create(op); | ||||
|          ops:=1; | ||||
|          loadsymbol(0,_op1,_op1ofs); | ||||
|       end; | ||||
| 
 | ||||
| 
 | ||||
|      constructor taicpu.op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint); | ||||
|       begin | ||||
|          inherited create(op); | ||||
|          ops:=2; | ||||
|          loadreg(0,_op1); | ||||
|          loadsymbol(1,_op2,_op2ofs); | ||||
|       end; | ||||
| 
 | ||||
| 
 | ||||
|     constructor taicpu.op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference); | ||||
|       begin | ||||
|          inherited create(op); | ||||
|          ops:=2; | ||||
|          loadsymbol(0,_op1,_op1ofs); | ||||
|          loadref(1,_op2); | ||||
|       end; | ||||
| 
 | ||||
| 
 | ||||
| { ****************************** newra stuff *************************** } | ||||
| 
 | ||||
|     function taicpu.is_same_reg_move(regtype: Tregistertype):boolean; | ||||
|       begin | ||||
|         { allow the register allocator to remove unnecessary moves } | ||||
|         result:=(((opcode=A_MOVE) and (regtype = R_INTREGISTER)) or | ||||
|                  ((opcode=A_MOVF) and (regtype = R_FPUREGISTER)) | ||||
|                 ) and | ||||
|                 (condition=C_None) and | ||||
|                 (ops=2) and | ||||
|                 (oper[0]^.typ=top_reg) and | ||||
|                 (oper[1]^.typ=top_reg) and | ||||
|                 (oper[0]^.reg=oper[1]^.reg); | ||||
|       end; | ||||
| 
 | ||||
| 
 | ||||
|     function spilling_create_load(const ref:treference;r:tregister): tai; | ||||
|       begin | ||||
|         case getregtype(r) of | ||||
|           R_INTREGISTER : | ||||
|             result:=taicpu.op_reg_ref(A_LDR,r,ref); | ||||
|           R_FPUREGISTER : | ||||
|             { use lfm because we don't know the current internal format | ||||
|               and avoid exceptions | ||||
|             } | ||||
|             result:=taicpu.op_reg_const_ref(A_LFM,r,1,ref); | ||||
|           else | ||||
|             internalerror(200401041); | ||||
|         end; | ||||
|       end; | ||||
| 
 | ||||
| 
 | ||||
|     function spilling_create_store(r:tregister; const ref:treference): tai; | ||||
|       begin | ||||
|         case getregtype(r) of | ||||
|           R_INTREGISTER : | ||||
|             result:=taicpu.op_reg_ref(A_STR,r,ref); | ||||
|           R_FPUREGISTER : | ||||
|             { use sfm because we don't know the current internal format | ||||
|               and avoid exceptions | ||||
|             } | ||||
|             result:=taicpu.op_reg_const_ref(A_SFM,r,1,ref); | ||||
|           else | ||||
|             internalerror(200401041); | ||||
|         end; | ||||
|       end; | ||||
| function taicpu.is_same_reg_move(regtype: Tregistertype): boolean; | ||||
| begin | ||||
|   Result := ( | ||||
|     ((opcode = A_MOVE) and (regtype = R_INTREGISTER)) or | ||||
|     ((regtype = R_FPUREGISTER) and (opcode in [A_MOV_S, A_MOV_D])) | ||||
|     ) and | ||||
|     (oper[0]^.reg = oper[1]^.reg); | ||||
| end; | ||||
| 
 | ||||
| 
 | ||||
|     function taicpu.spilling_get_operation_type(opnr: longint): topertype; | ||||
|       type | ||||
|         op_write_set_type =  set of TAsmOp; | ||||
|       const | ||||
|         op_write_set: op_write_set_type = | ||||
|       [A_NEG, | ||||
|       A_NEGU, | ||||
|       A_LI, | ||||
|       A_DLI, | ||||
|       A_LA, | ||||
|       A_MOVE, | ||||
|       A_LB, | ||||
|       A_LBU, | ||||
|       A_LH, | ||||
|       A_LHU, | ||||
|       A_LW, | ||||
|       A_LWU, | ||||
|       A_LWL, | ||||
|       A_LWR, | ||||
|       A_LD, | ||||
|       A_LDL, | ||||
|       A_LDR, | ||||
|       A_LL, | ||||
|       A_LLD, | ||||
|       A_ADDI, | ||||
|       A_DADDI, | ||||
|       A_ADDIU, | ||||
|       A_DADDIU, | ||||
|       A_SLTI, | ||||
|       A_SLTIU, | ||||
|       A_ANDI, | ||||
|       A_ORI, | ||||
|       A_XORI, | ||||
|       A_LUI, | ||||
|       A_DNEG, | ||||
|       A_DNEGU, | ||||
|       A_ADD, | ||||
|       A_DADD, | ||||
|       A_ADDU, | ||||
|       A_DADDU, | ||||
|       A_SUB, | ||||
|       A_DSUB, | ||||
|       A_SUBU, | ||||
|       A_DSUBU, | ||||
|       A_SLT, | ||||
|       A_SLTU, | ||||
|       A_AND, | ||||
|       A_OR, | ||||
|       A_XOR, | ||||
|       A_NOR, | ||||
|       A_MUL, | ||||
|       A_MULO, | ||||
|       A_MULOU, | ||||
|       A_DMUL, | ||||
|       A_DMULO, | ||||
|       A_DMULOU, | ||||
|       A_DIV, | ||||
|       A_DIVU, | ||||
|       A_DDIV, | ||||
|       A_DDIVU, | ||||
|       A_REM, | ||||
|       A_REMU, | ||||
|       A_DREM, | ||||
|       A_DREMU, | ||||
|       A_MULT, | ||||
|       A_DMULT, | ||||
|       A_MULTU, | ||||
|       A_DMULTU, | ||||
|       A_MFHI, | ||||
|       A_MFLO, | ||||
|       A_MULTG, | ||||
|       A_DMULTG, | ||||
|       A_MULTUG, | ||||
|       A_DMULTUG, | ||||
|       A_DIVG, | ||||
|       A_DDIVG, | ||||
|       A_DIVUG, | ||||
|       A_DDIVUG, | ||||
|       A_MODG, | ||||
|       A_DMODG, | ||||
|       A_MODUG, | ||||
|       A_DMODUG, | ||||
| 
 | ||||
|       A_SLL, | ||||
|       A_SRL, | ||||
|       A_SRA, | ||||
|       A_SLLV, | ||||
|       A_SRLV, | ||||
|       A_SRAV, | ||||
|       A_DSLL, | ||||
|       A_DSRL, | ||||
|       A_DSRA, | ||||
|       A_DSLLV, | ||||
|       A_DSRLV, | ||||
|       A_DSRAV, | ||||
|       A_DSLL32, | ||||
|       A_DSRL32, | ||||
|       A_DSRA32, | ||||
|       A_LWC1, | ||||
|       A_LDC1, | ||||
| 
 | ||||
| 
 | ||||
|       A_ADD_S, | ||||
|       A_ADD_D, | ||||
|       A_SUB_S, | ||||
|       A_SUB_D, | ||||
|       A_MUL_S, | ||||
|       A_MUL_D, | ||||
|       A_DIV_S, | ||||
|       A_DIV_D, | ||||
|       A_ABS_S, | ||||
|       A_ABS_D, | ||||
|       A_NEG_S, | ||||
|       A_NEG_D, | ||||
|       A_SQRT_S, | ||||
|       A_SQRT_D, | ||||
|       A_MOV_S, | ||||
|       A_MOV_D, | ||||
|       A_CVT_S_D, | ||||
|       A_CVT_S_W, | ||||
|       A_CVT_S_L, | ||||
|       A_CVT_D_S, | ||||
|       A_CVT_D_W, | ||||
|       A_CVT_D_L, | ||||
|       A_CVT_W_S, | ||||
|       A_CVT_W_D, | ||||
|       A_CVT_L_S, | ||||
|       A_CVT_L_D, | ||||
|       A_ROUND_W_S, | ||||
|       A_ROUND_W_D, | ||||
|       A_ROUND_L_S, | ||||
|       A_ROUND_L_D, | ||||
|       A_TRUNC_W_S, | ||||
|       A_TRUNC_W_D, | ||||
|       A_TRUNC_L_S, | ||||
|       A_TRUNC_L_D, | ||||
|       A_CEIL_W_S, | ||||
|       A_CEIL_W_D, | ||||
|       A_CEIL_L_S, | ||||
|       A_CEIL_L_D, | ||||
|       A_FLOOR_W_S, | ||||
|       A_FLOOR_W_D, | ||||
|       A_FLOOR_L_S, | ||||
|       A_FLOOR_L_D, | ||||
|       A_SEQ, | ||||
|       A_SGE, | ||||
|       A_SGEU, | ||||
|       A_SGT, | ||||
|       A_SGTU, | ||||
|       A_SLE, | ||||
|       A_SLEU, | ||||
|       A_SNE]; | ||||
| 
 | ||||
|       begin | ||||
|         case opcode of | ||||
|           A_ADC,A_ADD,A_AND, | ||||
|           A_EOR,A_CLZ, | ||||
|           A_LDR,A_LDRB,A_LDRD,A_LDRBT,A_LDRH,A_LDRSB, | ||||
|           A_LDRSH,A_LDRT, | ||||
|           A_MOV,A_MVN,A_MLA,A_MUL, | ||||
|           A_ORR,A_RSB,A_RSC,A_SBC,A_SUB, | ||||
|           A_SWP,A_SWPB, | ||||
|           A_LDF,A_FLT,A_FIX, | ||||
|           A_ADF,A_DVF,A_FDV,A_FML, | ||||
|           A_RFS,A_RFC,A_RDF, | ||||
|           A_RMF,A_RPW,A_RSF,A_SUF,A_ABS,A_ACS,A_ASN,A_ATN,A_COS, | ||||
|           A_EXP,A_LOG,A_LGN,A_MVF,A_MNF,A_FRD,A_MUF,A_POL,A_RND,A_SIN,A_SQT,A_TAN, | ||||
|           A_LFM: | ||||
|             if opnr=0 then | ||||
|               result:=operand_write | ||||
|             else | ||||
|               result:=operand_read; | ||||
|           A_BIC,A_BKPT,A_B,A_BL,A_BLX,A_BX, | ||||
|           A_CMN,A_CMP,A_TEQ,A_TST, | ||||
|           A_CMF,A_CMFE,A_WFS,A_CNF: | ||||
|             result:=operand_read; | ||||
|           A_SMLAL,A_UMLAL: | ||||
|             if opnr in [0,1] then | ||||
|               result:=operand_readwrite | ||||
|             else | ||||
|               result:=operand_read; | ||||
|            A_SMULL,A_UMULL: | ||||
|             if opnr in [0,1] then | ||||
|               result:=operand_write | ||||
|             else | ||||
|               result:=operand_read; | ||||
|           A_STR,A_STRB,A_STRBT,A_STRD, | ||||
|           A_STRH,A_STRT,A_STF,A_SFM: | ||||
|             { important is what happens with the involved registers } | ||||
|             if opnr=0 then | ||||
|               result := operand_read | ||||
|             else | ||||
|               { check for pre/post indexed } | ||||
|               result := operand_read; | ||||
|         result := operand_read; | ||||
|         if opcode in op_write_set then | ||||
|           if opnr = 0 then | ||||
|             result := operand_write; | ||||
|       end; | ||||
| 
 | ||||
| 
 | ||||
|     function spilling_create_load(const ref: treference; r: tregister): taicpu; | ||||
|       begin | ||||
|         case getregtype(r) of | ||||
|           R_INTREGISTER : | ||||
|             result:=taicpu.op_reg_ref(A_LW,r,ref); | ||||
|           R_FPUREGISTER : | ||||
|             begin | ||||
|               case getsubreg(r) of | ||||
|                 R_SUBFS : | ||||
|                   result:=taicpu.op_reg_ref(A_LWC1,r,ref); | ||||
|                 R_SUBFD : | ||||
|                   result:=taicpu.op_reg_ref(A_LDC1,r,ref); | ||||
|                 else | ||||
|                   internalerror(200401042); | ||||
|               end; | ||||
|             end | ||||
|           else | ||||
|             internalerror(200403151); | ||||
|             internalerror(200401041); | ||||
|         end; | ||||
|       end; | ||||
| 
 | ||||
| 
 | ||||
|     procedure InitAsm; | ||||
|     function spilling_create_store(r: tregister; const ref: treference): taicpu; | ||||
|       begin | ||||
|         case getregtype(r) of | ||||
|           R_INTREGISTER : | ||||
|             result:=taicpu.op_reg_ref(A_SW,r,ref); | ||||
|           R_FPUREGISTER : | ||||
|             begin | ||||
|               case getsubreg(r) of | ||||
|                 R_SUBFS : | ||||
|                   result:=taicpu.op_reg_ref(A_SWC1,r,ref); | ||||
|                 R_SUBFD : | ||||
|                   result:=taicpu.op_reg_ref(A_SDC1,r,ref); | ||||
|                 else | ||||
|                   internalerror(200401042); | ||||
|               end; | ||||
|             end | ||||
|           else | ||||
|             internalerror(200401041); | ||||
|         end; | ||||
|       end; | ||||
| 
 | ||||
| 
 | ||||
|     procedure DoneAsm; | ||||
|       begin | ||||
|       end; | ||||
| procedure InitAsm; | ||||
|   begin | ||||
|   end; | ||||
| 
 | ||||
| 
 | ||||
| procedure DoneAsm; | ||||
|   begin | ||||
|   end; | ||||
| 
 | ||||
| 
 | ||||
| begin | ||||
|   cai_cpu   := taicpu; | ||||
|   cai_align := tai_align; | ||||
| end. | ||||
|  | ||||
							
								
								
									
										41
									
								
								compiler/mips/aoptcpu.pas
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								compiler/mips/aoptcpu.pas
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | ||||
| { | ||||
|     Copyright (c) 1998-2004 by Jonas Maebe | ||||
| 
 | ||||
|     This unit calls the optimization procedures to optimize the assembler | ||||
|     code for sparc | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program; if not, write to the Free Software | ||||
|     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
| 
 | ||||
|  **************************************************************************** | ||||
| } | ||||
| 
 | ||||
| unit aoptcpu; | ||||
| 
 | ||||
| {$i fpcdefs.inc} | ||||
| 
 | ||||
|   Interface | ||||
| 
 | ||||
|     uses | ||||
|       cpubase, aoptobj, aoptcpub, aopt; | ||||
| 
 | ||||
|     Type | ||||
|       TCpuAsmOptimizer = class(TAsmOptimizer) | ||||
|       End; | ||||
| 
 | ||||
|   Implementation | ||||
| 
 | ||||
| begin | ||||
|   casmoptimizer:=TCpuAsmOptimizer; | ||||
| end. | ||||
							
								
								
									
										119
									
								
								compiler/mips/aoptcpub.pas
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								compiler/mips/aoptcpub.pas
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,119 @@ | ||||
|  { | ||||
|     Copyright (c) 1998-2009 by Jonas Maebe and David Zhang | ||||
| 
 | ||||
|     This unit contains several types and constants necessary for the | ||||
|     optimizer to work on the MIPSEL architecture | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program; if not, write to the Free Software | ||||
|     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
| 
 | ||||
|  **************************************************************************** | ||||
| } | ||||
| Unit aoptcpub; { Assembler OPTimizer CPU specific Base } | ||||
| 
 | ||||
| {$i fpcdefs.inc} | ||||
| 
 | ||||
| { enable the following define if memory references can have both a base and } | ||||
| { index register in 1 operand                                               } | ||||
| 
 | ||||
| {$define RefsHaveIndexReg} | ||||
| 
 | ||||
| { enable the following define if memory references can have a scaled index } | ||||
| 
 | ||||
| { define RefsHaveScale} | ||||
| 
 | ||||
| { enable the following define if memory references can have a segment } | ||||
| { override                                                            } | ||||
| 
 | ||||
| { define RefsHaveSegment} | ||||
| 
 | ||||
| Interface | ||||
| 
 | ||||
| Uses | ||||
|   cpubase,aasmcpu,AOptBase; | ||||
| 
 | ||||
| Type | ||||
| 
 | ||||
| { type of a normal instruction } | ||||
|   TInstr = Taicpu; | ||||
|   PInstr = ^TInstr; | ||||
| 
 | ||||
| { ************************************************************************* } | ||||
| { **************************** TCondRegs ********************************** } | ||||
| { ************************************************************************* } | ||||
| { Info about the conditional registers                                      } | ||||
|   TCondRegs = Object | ||||
|     Constructor Init; | ||||
|     Destructor Done; | ||||
|   End; | ||||
| 
 | ||||
| { ************************************************************************* } | ||||
| { **************************** TAoptBaseCpu ******************************* } | ||||
| { ************************************************************************* } | ||||
| 
 | ||||
|   TAoptBaseCpu = class(TAoptBase) | ||||
|   End; | ||||
| 
 | ||||
| 
 | ||||
| { ************************************************************************* } | ||||
| { ******************************* Constants ******************************* } | ||||
| { ************************************************************************* } | ||||
| Const | ||||
| 
 | ||||
| { the maximum number of things (registers, memory, ...) a single instruction } | ||||
| { changes                                                                    } | ||||
| 
 | ||||
|   MaxCh = 3; | ||||
| 
 | ||||
| { the maximum number of operands an instruction has } | ||||
| 
 | ||||
|   MaxOps = 3; | ||||
| 
 | ||||
| {Oper index of operand that contains the source (reference) with a load } | ||||
| {instruction                                                            } | ||||
| 
 | ||||
|   LoadSrc = 0; | ||||
| 
 | ||||
| {Oper index of operand that contains the destination (register) with a load } | ||||
| {instruction                                                                } | ||||
| 
 | ||||
|   LoadDst = 1; | ||||
| 
 | ||||
| {Oper index of operand that contains the source (register) with a store } | ||||
| {instruction                                                            } | ||||
| 
 | ||||
|   StoreSrc = 0; | ||||
| 
 | ||||
| {Oper index of operand that contains the destination (reference) with a load } | ||||
| {instruction                                                                 } | ||||
| 
 | ||||
|   StoreDst = 1; | ||||
| 
 | ||||
|   aopt_uncondjmp = A_J; | ||||
|   aopt_condjmp = A_BEQ; | ||||
| 
 | ||||
| Implementation | ||||
| 
 | ||||
| { ************************************************************************* } | ||||
| { **************************** TCondRegs ********************************** } | ||||
| { ************************************************************************* } | ||||
| Constructor TCondRegs.init; | ||||
| Begin | ||||
| End; | ||||
| 
 | ||||
| Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl} | ||||
| Begin | ||||
| End; | ||||
| 
 | ||||
| End. | ||||
							
								
								
									
										36
									
								
								compiler/mips/aoptcpud.pas
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								compiler/mips/aoptcpud.pas
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| { | ||||
|     Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal | ||||
|     Development Team | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program; if not, write to the Free Software | ||||
|     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
| 
 | ||||
|  **************************************************************************** | ||||
| } | ||||
| Unit aoptcpud; | ||||
| 
 | ||||
| {$i fpcdefs.inc} | ||||
| 
 | ||||
|   interface | ||||
| 
 | ||||
|     uses | ||||
|       aoptda; | ||||
| 
 | ||||
|     type | ||||
|       TAOptDFACpu = class(TAOptDFA) | ||||
|       end; | ||||
| 
 | ||||
|   implementation | ||||
| 
 | ||||
| end. | ||||
| @ -101,7 +101,7 @@ type | ||||
|     procedure a_op64_reg_reg_reg_checkoverflow(list: tasmlist; op: TOpCG; size: tcgsize; regsrc1, regsrc2, regdst: tregister64; setflags: boolean; var ovloc: tlocation); override; | ||||
|   end; | ||||
| 
 | ||||
| 
 | ||||
|   procedure create_codegen; | ||||
| 
 | ||||
| implementation | ||||
| 
 | ||||
| @ -336,20 +336,20 @@ begin | ||||
|     (ref.offset > simm16hi) then | ||||
|   begin | ||||
|     tmpreg := GetIntRegister(list, OS_INT); | ||||
|     reference_reset(tmpref); | ||||
|     reference_reset(tmpref,sizeof(aint)); | ||||
|     tmpref.symbol  := ref.symbol; | ||||
|     tmpref.offset  := ref.offset; | ||||
|     tmpref.refaddr := addr_hi; | ||||
|     tmpref.refaddr := addr_high; | ||||
|     list.concat(taicpu.op_reg_ref(A_LUI, tmpreg, tmpref)); | ||||
|     if (ref.offset = 0) and (ref.index = NR_NO) and | ||||
|       (ref.base = NR_NO) then | ||||
|     begin | ||||
|       ref.refaddr := addr_lo; | ||||
|       ref.refaddr := addr_low; | ||||
|     end | ||||
|     else | ||||
|     begin | ||||
|       { Load the low part is left } | ||||
|       tmpref.refaddr := addr_lo; | ||||
|       tmpref.refaddr := addr_low; | ||||
|       list.concat(taicpu.op_reg_reg_ref(A_ADDIU, tmpreg, tmpreg, tmpref)); | ||||
|       ref.offset := 0; | ||||
|       { symbol is loaded } | ||||
| @ -405,7 +405,7 @@ begin | ||||
|     assigned(ref.symbol) then | ||||
|   begin | ||||
|     tmpreg := GetIntRegister(list, OS_INT); | ||||
|     reference_reset(tmpref); | ||||
|     reference_reset(tmpref,sizeof(aint)); | ||||
|     tmpref.symbol  := ref.symbol; | ||||
|     tmpref.refaddr := addr_pic; | ||||
|     if not (pi_needs_got in current_procinfo.flags) then | ||||
| @ -435,14 +435,14 @@ begin | ||||
|   tmpreg1 := GetIntRegister(list, OS_INT); | ||||
|   if assigned(ref.symbol) then | ||||
|   begin | ||||
|     reference_reset(tmpref); | ||||
|     reference_reset(tmpref,sizeof(aint)); | ||||
|     tmpref.symbol  := ref.symbol; | ||||
|     tmpref.offset  := ref.offset; | ||||
|     tmpref.refaddr := addr_hi; | ||||
|     tmpref.refaddr := addr_high; | ||||
|     list.concat(taicpu.op_reg_ref(A_LUI, tmpreg1, tmpref)); | ||||
|     { Load the low part } | ||||
| 
 | ||||
|     tmpref.refaddr := addr_lo; | ||||
|     tmpref.refaddr := addr_low; | ||||
|     list.concat(taicpu.op_reg_reg_ref(A_ADDIU, tmpreg1, tmpreg1, tmpref)); | ||||
|     { symbol is loaded } | ||||
|     ref.symbol := nil; | ||||
| @ -554,7 +554,7 @@ begin | ||||
|       begin | ||||
|         if (Index = NR_SP) and (Offset < Target_info.first_parm_offset) then | ||||
|           InternalError(2002081104); | ||||
|         reference_reset_base(ref, index, offset); | ||||
|         reference_reset_base(ref, index, offset, sizeof(aint)); | ||||
|       end; | ||||
|       a_load_const_ref(list, size, a, ref); | ||||
|     end; | ||||
| @ -581,7 +581,7 @@ begin | ||||
|         begin | ||||
|           if (Index = NR_SP) and (Offset < Target_info.first_parm_offset) then | ||||
|             InternalError(2002081104); | ||||
|           reference_reset_base(ref, index, offset); | ||||
|           reference_reset_base(ref, index, offset, sizeof(aint)); | ||||
|         end; | ||||
|         tmpreg := GetIntRegister(list, OS_INT); | ||||
|         a_load_ref_reg(list, sz, sz, r, tmpreg); | ||||
| @ -607,7 +607,7 @@ begin | ||||
|         a_loadaddr_ref_reg(list, r, Register); | ||||
|       LOC_REFERENCE: | ||||
|       begin | ||||
|         reference_reset(ref); | ||||
|         reference_reset(ref,sizeof(aint)); | ||||
|         ref.base   := reference.index; | ||||
|         ref.offset := reference.offset; | ||||
|         tmpreg     := GetAddressRegister(list); | ||||
| @ -635,7 +635,7 @@ begin | ||||
|         a_load_ref_reg(list, hloc^.size, hloc^.size, href, hloc^.Register); | ||||
|       LOC_REFERENCE: | ||||
|       begin | ||||
|         reference_reset_base(href2, hloc^.reference.index, hloc^.reference.offset); | ||||
|         reference_reset_base(href2, hloc^.reference.index, hloc^.reference.offset, sizeof(aint)); | ||||
|         a_load_ref_ref(list, hloc^.size, hloc^.size, href, href2); | ||||
|       end; | ||||
|       else | ||||
| @ -651,16 +651,16 @@ procedure TCgMPSel.a_paramfpu_reg(list: tasmlist; size: tcgsize; const r: tregis | ||||
| var | ||||
|   href: treference; | ||||
| begin | ||||
|   tg.GetTemp(list, TCGSize2Size[size], tt_normal, href); | ||||
|   a_loadfpu_reg_ref(list, size, r, href); | ||||
|   tg.GetTemp(list, TCGSize2Size[size], sizeof(aint), tt_normal, href); | ||||
|   a_loadfpu_reg_ref(list, size, size, r, href); | ||||
|   a_paramfpu_ref(list, size, href, paraloc); | ||||
|   tg.Ungettemp(list, href); | ||||
| end; | ||||
| 
 | ||||
| 
 | ||||
| procedure TCgMPSel.a_call_name(list: tasmlist; const s: string); | ||||
| procedure TCgMPSel.a_call_name(list: tasmlist; const s: string; weak: boolean); | ||||
| begin | ||||
|   list.concat(taicpu.op_sym(A_JAL, objectlibrary.newasmsymbol(s, AB_EXTERNAL, AT_FUNCTION))); | ||||
|   list.concat(taicpu.op_sym(A_JAL,current_asmdata.RefAsmSymbol(s))); | ||||
|   { Delay slot } | ||||
|   list.concat(taicpu.op_none(A_NOP)); | ||||
| end; | ||||
| @ -827,7 +827,7 @@ begin | ||||
|   begin | ||||
|     tmpreg := r; //GetIntRegister(list, OS_ADDR); | ||||
|     r_used := true; | ||||
|     reference_reset(tmpref); | ||||
|     reference_reset(tmpref,sizeof(aint)); | ||||
|     tmpref.symbol  := href.symbol; | ||||
|     tmpref.refaddr := addr_pic; | ||||
|     if not (pi_needs_got in current_procinfo.flags) then | ||||
| @ -858,13 +858,13 @@ begin | ||||
|       hreg := r | ||||
|     else | ||||
|       hreg := GetAddressRegister(list); | ||||
|     reference_reset(tmpref); | ||||
|     reference_reset(tmpref,sizeof(aint)); | ||||
|     tmpref.symbol  := href.symbol; | ||||
|     tmpref.offset  := href.offset; | ||||
|     tmpref.refaddr := addr_hi; | ||||
|     tmpref.refaddr := addr_high; | ||||
|     list.concat(taicpu.op_reg_ref(A_LUI, hreg, tmpref)); | ||||
|     { Only the low part is left } | ||||
|     tmpref.refaddr := addr_lo; | ||||
|     tmpref.refaddr := addr_low; | ||||
|     list.concat(taicpu.op_reg_reg_ref(A_ADDIU, hreg, hreg, tmpref)); | ||||
|     if href.base <> NR_NO then | ||||
|     begin | ||||
| @ -880,8 +880,7 @@ begin | ||||
|   else | ||||
|   { At least small offset, maybe base and maybe index } | ||||
|   if  (href.offset >= simm16lo) and | ||||
|     (href.offset <= simm16hi) | ||||
|   then | ||||
|     (href.offset <= simm16hi) then | ||||
|   begin | ||||
|     if href.index <> NR_NO then   { Both base and index } | ||||
|     begin | ||||
| @ -903,8 +902,8 @@ begin | ||||
|     begin | ||||
|       list.concat(taicpu.op_reg_reg_const(A_ADDIU, r, href.base, href.offset)); | ||||
|     end | ||||
|     else { only offset, can be generated by absolute } | ||||
| 
 | ||||
|     else | ||||
|       { only offset, can be generated by absolute } | ||||
|       a_load_const_reg(list, OS_ADDR, href.offset, r); | ||||
|   end | ||||
|   else | ||||
| @ -920,10 +919,10 @@ var | ||||
| begin | ||||
|   if reg1 <> reg2 then | ||||
|   begin | ||||
|     instr := taicpu.op_reg_reg(fpumovinstr[size], reg2, reg1); | ||||
|     instr := taicpu.op_reg_reg(fpumovinstr[tosize], reg2, reg1); | ||||
|     list.Concat(instr); | ||||
|             { Notify the register allocator that we have written a move instruction so | ||||
|               it can try to eliminate it. } | ||||
|     { Notify the register allocator that we have written a move instruction so | ||||
|       it can try to eliminate it. } | ||||
|     add_move_instruction(instr); | ||||
|   end; | ||||
| end; | ||||
| @ -934,15 +933,11 @@ var | ||||
|   tmpref: treference; | ||||
|   tmpreg: tregister; | ||||
| begin | ||||
|   case size of | ||||
|   case tosize of | ||||
|     OS_F32: | ||||
|     begin | ||||
|       handle_load_store_fpu(list, False, A_LWC1, reg, ref); | ||||
|     end; | ||||
|     OS_F64: | ||||
|     begin | ||||
|       handle_load_store_fpu(list, False, A_LDC1, reg, ref); | ||||
|     end | ||||
|     else | ||||
|       InternalError(2007042701); | ||||
|   end; | ||||
| @ -953,15 +948,11 @@ var | ||||
|   tmpref: treference; | ||||
|   tmpreg: tregister; | ||||
| begin | ||||
|   case size of | ||||
|   case tosize of | ||||
|     OS_F32: | ||||
|     begin | ||||
|       handle_load_store_fpu(list, True, A_SWC1, reg, ref); | ||||
|     end; | ||||
|     OS_F64: | ||||
|     begin | ||||
|       handle_load_store_fpu(list, True, A_SDC1, reg, ref); | ||||
|     end | ||||
|     else | ||||
|       InternalError(2007042702); | ||||
|   end; | ||||
| @ -1237,59 +1228,58 @@ begin | ||||
|   list.concat(taicpu.op_reg_const(A_LI, tmpreg, a)); | ||||
| end; | ||||
|   case cmp_op of | ||||
|           OC_EQ:           { equality comparison              } | ||||
|             list.concat(taicpu.op_reg_reg_sym(A_BEQ, reg, tmpreg, l)); | ||||
|           OC_GT:           { greater than (signed)            } | ||||
|             list.concat(taicpu.op_reg_reg_sym(A_BGT, reg, tmpreg, l)); | ||||
|           OC_LT:           { less than (signed)               } | ||||
|             list.concat(taicpu.op_reg_reg_sym(A_BLT, reg, tmpreg, l)); | ||||
|           OC_GTE:          { greater or equal than (signed)   } | ||||
|             list.concat(taicpu.op_reg_reg_sym(A_BGE, reg, tmpreg, l)); | ||||
|           OC_LTE:          { less or equal than (signed)      } | ||||
|             list.concat(taicpu.op_reg_reg_sym(A_BLE, reg, tmpreg, l)); | ||||
|           OC_NE:           { not equal                        } | ||||
|             list.concat(taicpu.op_reg_reg_sym(A_BNE, reg, tmpreg, l)); | ||||
|           OC_BE:           { less or equal than (unsigned)    } | ||||
|             list.concat(taicpu.op_reg_reg_sym(A_BLEU, reg, tmpreg, l)); | ||||
|           OC_B:            { less than (unsigned)             } | ||||
|             list.concat(taicpu.op_reg_reg_sym(A_BLTU, reg, tmpreg, l)); | ||||
|           OC_AE:           { greater or equal than (unsigned) } | ||||
|             list.concat(taicpu.op_reg_reg_sym(A_BGEU, reg, tmpreg, l)); | ||||
|           OC_A:             { greater than (unsigned)          } | ||||
|             list.concat(taicpu.op_reg_reg_sym(A_BGTU, reg, tmpreg, l)); | ||||
|       else | ||||
|         internalerror(200701071); | ||||
|     end;{ case } | ||||
|     OC_EQ:           { equality comparison              } | ||||
|       list.concat(taicpu.op_reg_reg_sym(A_BEQ, reg, tmpreg, l)); | ||||
|     OC_GT:           { greater than (signed)            } | ||||
|       list.concat(taicpu.op_reg_reg_sym(A_BGT, reg, tmpreg, l)); | ||||
|     OC_LT:           { less than (signed)               } | ||||
|       list.concat(taicpu.op_reg_reg_sym(A_BLT, reg, tmpreg, l)); | ||||
|     OC_GTE:          { greater or equal than (signed)   } | ||||
|       list.concat(taicpu.op_reg_reg_sym(A_BGE, reg, tmpreg, l)); | ||||
|     OC_LTE:          { less or equal than (signed)      } | ||||
|       list.concat(taicpu.op_reg_reg_sym(A_BLE, reg, tmpreg, l)); | ||||
|     OC_NE:           { not equal                        } | ||||
|       list.concat(taicpu.op_reg_reg_sym(A_BNE, reg, tmpreg, l)); | ||||
|     OC_BE:           { less or equal than (unsigned)    } | ||||
|       list.concat(taicpu.op_reg_reg_sym(A_BLEU, reg, tmpreg, l)); | ||||
|     OC_B:            { less than (unsigned)             } | ||||
|       list.concat(taicpu.op_reg_reg_sym(A_BLTU, reg, tmpreg, l)); | ||||
|     OC_AE:           { greater or equal than (unsigned) } | ||||
|       list.concat(taicpu.op_reg_reg_sym(A_BGEU, reg, tmpreg, l)); | ||||
|     OC_A:             { greater than (unsigned)          } | ||||
|       list.concat(taicpu.op_reg_reg_sym(A_BGTU, reg, tmpreg, l)); | ||||
|     else | ||||
|       internalerror(200701071); | ||||
|   end; | ||||
|   list.Concat(TAiCpu.Op_none(A_NOP)); | ||||
| 
 | ||||
| end; | ||||
| 
 | ||||
| 
 | ||||
| procedure TCgMPSel.a_cmp_reg_reg_label(list: tasmlist; size: tcgsize; cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel); | ||||
| begin | ||||
|   case cmp_op of | ||||
|           OC_EQ:           { equality comparison              } | ||||
|             list.concat(taicpu.op_reg_reg_sym(A_BEQ, reg2, reg1, l)); | ||||
|           OC_GT:           { greater than (signed)            } | ||||
|             list.concat(taicpu.op_reg_reg_sym(A_BGT, reg2, reg1, l)); | ||||
|           OC_LT:           { less than (signed)               } | ||||
|             list.concat(taicpu.op_reg_reg_sym(A_BLT, reg2, reg1, l)); | ||||
|           OC_GTE:          { greater or equal than (signed)   } | ||||
|             list.concat(taicpu.op_reg_reg_sym(A_BGE, reg2, reg1, l)); | ||||
|           OC_LTE:          { less or equal than (signed)      } | ||||
|             list.concat(taicpu.op_reg_reg_sym(A_BLE, reg2, reg1, l)); | ||||
|           OC_NE:           { not equal                        } | ||||
|             list.concat(taicpu.op_reg_reg_sym(A_BNE, reg2, reg1, l)); | ||||
|           OC_BE:           { less or equal than (unsigned)    } | ||||
|             list.concat(taicpu.op_reg_reg_sym(A_BLEU, reg2, reg1, l)); | ||||
|           OC_B:            { less than (unsigned)             } | ||||
|             list.concat(taicpu.op_reg_reg_sym(A_BLTU, reg2, reg1, l)); | ||||
|           OC_AE:           { greater or equal than (unsigned) } | ||||
|             list.concat(taicpu.op_reg_reg_sym(A_BGEU, reg2, reg1, l)); | ||||
|           OC_A:             { greater than (unsigned)          } | ||||
|             list.concat(taicpu.op_reg_reg_sym(A_BGTU, reg2, reg1, l)); | ||||
|       else | ||||
|         internalerror(200701072); | ||||
|     OC_EQ:           { equality comparison              } | ||||
|       list.concat(taicpu.op_reg_reg_sym(A_BEQ, reg2, reg1, l)); | ||||
|     OC_GT:           { greater than (signed)            } | ||||
|       list.concat(taicpu.op_reg_reg_sym(A_BGT, reg2, reg1, l)); | ||||
|     OC_LT:           { less than (signed)               } | ||||
|       list.concat(taicpu.op_reg_reg_sym(A_BLT, reg2, reg1, l)); | ||||
|     OC_GTE:          { greater or equal than (signed)   } | ||||
|       list.concat(taicpu.op_reg_reg_sym(A_BGE, reg2, reg1, l)); | ||||
|     OC_LTE:          { less or equal than (signed)      } | ||||
|       list.concat(taicpu.op_reg_reg_sym(A_BLE, reg2, reg1, l)); | ||||
|     OC_NE:           { not equal                        } | ||||
|       list.concat(taicpu.op_reg_reg_sym(A_BNE, reg2, reg1, l)); | ||||
|     OC_BE:           { less or equal than (unsigned)    } | ||||
|       list.concat(taicpu.op_reg_reg_sym(A_BLEU, reg2, reg1, l)); | ||||
|     OC_B:            { less than (unsigned)             } | ||||
|       list.concat(taicpu.op_reg_reg_sym(A_BLTU, reg2, reg1, l)); | ||||
|     OC_AE:           { greater or equal than (unsigned) } | ||||
|       list.concat(taicpu.op_reg_reg_sym(A_BGEU, reg2, reg1, l)); | ||||
|     OC_A:             { greater than (unsigned)          } | ||||
|       list.concat(taicpu.op_reg_reg_sym(A_BGTU, reg2, reg1, l)); | ||||
|     else | ||||
|       internalerror(200701072); | ||||
|     end;{ case } | ||||
|   list.Concat(TAiCpu.Op_none(A_NOP)); | ||||
| end; | ||||
| @ -1297,7 +1287,7 @@ end; | ||||
| 
 | ||||
| procedure TCgMPSel.a_jmp_always(List: tasmlist; l: TAsmLabel); | ||||
| begin | ||||
|   List.Concat(TAiCpu.op_sym(A_J, objectlibrary.newasmsymbol(l.Name, AB_EXTERNAL, AT_FUNCTION))); | ||||
|   List.Concat(TAiCpu.op_sym(A_J,l)); | ||||
|   { Delay slot } | ||||
|   list.Concat(TAiCpu.Op_none(A_NOP)); | ||||
| end; | ||||
| @ -1305,7 +1295,7 @@ end; | ||||
| 
 | ||||
| procedure TCgMPSel.a_jmp_name(list: tasmlist; const s: string); | ||||
| begin | ||||
|   List.Concat(TAiCpu.op_sym(A_J, objectlibrary.newasmsymbol(s, AB_EXTERNAL, AT_FUNCTION))); | ||||
|   List.Concat(TAiCpu.op_sym(A_J, current_asmdata.RefAsmSymbol(s))); | ||||
|   { Delay slot } | ||||
|   list.Concat(TAiCpu.Op_none(A_NOP)); | ||||
| end; | ||||
| @ -1410,9 +1400,9 @@ var | ||||
|   localsize: aint; | ||||
| begin | ||||
|   localsize := cgcpu_calc_stackframe_size; | ||||
|   if paramanager.ret_in_param(current_procinfo.procdef.rettype.def, current_procinfo.procdef.proccalloption) then | ||||
|   if paramanager.ret_in_param(current_procinfo.procdef.returndef, current_procinfo.procdef.proccalloption) then | ||||
|   begin | ||||
|     reference_reset(hr); | ||||
|     reference_reset(hr,sizeof(aint)); | ||||
|     hr.offset  := 12; | ||||
|     hr.refaddr := addr_full; | ||||
|     if nostackframe then | ||||
| @ -1488,7 +1478,7 @@ begin | ||||
|   paramanager.freeparaloc(list, paraloc1); | ||||
|   alloccpuregisters(list, R_INTREGISTER, paramanager.get_volatile_registers_int(pocall_default)); | ||||
|   alloccpuregisters(list, R_FPUREGISTER, paramanager.get_volatile_registers_fpu(pocall_default)); | ||||
|   a_call_name(list, 'FPC_MOVE'); | ||||
|   a_call_name(list, 'FPC_MOVE', false); | ||||
|   dealloccpuregisters(list, R_FPUREGISTER, paramanager.get_volatile_registers_fpu(pocall_default)); | ||||
|   dealloccpuregisters(list, R_INTREGISTER, paramanager.get_volatile_registers_int(pocall_default)); | ||||
|   paraloc3.done; | ||||
| @ -1511,8 +1501,8 @@ begin | ||||
|     g_concatcopy_move(list, Source, dest, len) | ||||
|   else | ||||
|   begin | ||||
|     reference_reset(src); | ||||
|     reference_reset(dst); | ||||
|     reference_reset(src,sizeof(aint)); | ||||
|     reference_reset(dst,sizeof(aint)); | ||||
|     { load the address of source into src.base } | ||||
|     src.base := GetAddressRegister(list); | ||||
|     a_loadaddr_ref_reg(list, Source, src.base); | ||||
| @ -1532,7 +1522,7 @@ begin | ||||
|       a_load_const_reg(list, OS_INT, Count, countreg); | ||||
|       { explicitely allocate R_O0 since it can be used safely here } | ||||
|       { (for holding date that's being copied)                    } | ||||
|       objectlibrary.getlabel(lab); | ||||
|       current_asmdata.getjumplabel(lab); | ||||
|       a_label(list, lab); | ||||
|       list.concat(taicpu.op_reg_ref(A_LW, tmpreg1, src)); | ||||
|       list.concat(taicpu.op_reg_ref(A_SW, tmpreg1, dst)); | ||||
| @ -1595,8 +1585,8 @@ begin | ||||
|     g_concatcopy_move(list, Source, dest, len) | ||||
|   else | ||||
|   begin | ||||
|     reference_reset(src); | ||||
|     reference_reset(dst); | ||||
|     reference_reset(src,sizeof(aint)); | ||||
|     reference_reset(dst,sizeof(aint)); | ||||
|     { load the address of source into src.base } | ||||
|     src.base := GetAddressRegister(list); | ||||
|     a_loadaddr_ref_reg(list, Source, src.base); | ||||
| @ -1615,7 +1605,7 @@ begin | ||||
|       a_load_const_reg(list, OS_INT, len, countreg); | ||||
|       { explicitely allocate R_O0 since it can be used safely here } | ||||
|       { (for holding date that's being copied)                    } | ||||
|       objectlibrary.getlabel(lab); | ||||
|       current_asmdata.getjumplabel(lab); | ||||
|       a_label(list, lab); | ||||
|       list.concat(taicpu.op_reg_ref(A_LBU, tmpreg1, src)); | ||||
|       list.concat(taicpu.op_reg_ref(A_SB, tmpreg1, dst)); | ||||
| @ -1646,7 +1636,7 @@ procedure TCgMPSel.g_intf_wrapper(list: tasmlist; procdef: tprocdef; const label | ||||
|         var | ||||
|           href: treference; | ||||
|         begin | ||||
|           reference_reset_base(href, NR_R2, 0);  { return value } | ||||
|           reference_reset_base(href, NR_R2, 0, sizeof(aint));  { return value } | ||||
|           cg.a_load_ref_reg(list, OS_ADDR, OS_ADDR, href, NR_R24); | ||||
|         end; | ||||
| 
 | ||||
| @ -1658,7 +1648,7 @@ procedure TCgMPSel.g_intf_wrapper(list: tasmlist; procdef: tprocdef; const label | ||||
|           if (procdef.extnumber=$ffff) then | ||||
|             Internalerror(200006139); | ||||
|           { call/jmp  vmtoffs(%eax) ; method offs } | ||||
|           reference_reset_base(href, NR_R24, procdef._class.vmtmethodoffset(procdef.extnumber)); | ||||
|           reference_reset_base(href, NR_R24, procdef._class.vmtmethodoffset(procdef.extnumber), sizeof(aint)); | ||||
|           cg.a_load_ref_reg(list, OS_ADDR, OS_ADDR, href, NR_R24); | ||||
|           list.concat(taicpu.op_reg(A_JR, NR_R24)); | ||||
|         end; | ||||
| @ -1694,7 +1684,7 @@ begin | ||||
|     op_onr24methodaddr; | ||||
|   end | ||||
|   else | ||||
|    list.concat(taicpu.op_sym(A_B, objectlibrary.newasmsymbol(procdef.mangledname, AB_EXTERNAL, AT_FUNCTION))); | ||||
|    list.concat(taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol(procdef.mangledname))); | ||||
|   { Delay slot } | ||||
|   list.Concat(TAiCpu.Op_none(A_NOP)); | ||||
| 
 | ||||
| @ -1966,7 +1956,10 @@ begin | ||||
| end; | ||||
| 
 | ||||
| 
 | ||||
| begin | ||||
|   cg   := TCgMPSel.Create; | ||||
|   cg64 := TCg64MPSel.Create; | ||||
|     procedure create_codegen; | ||||
|       begin | ||||
|         cg:=TCgMPSel.Create; | ||||
|         cg64:=TCg64MPSel.Create; | ||||
|       end; | ||||
| 
 | ||||
| end. | ||||
|  | ||||
| @ -296,11 +296,21 @@ unit cpubase; | ||||
|       } | ||||
|       std_param_align = 4; | ||||
| 
 | ||||
| {***************************************************************************** | ||||
|                             CPU Dependent Constants | ||||
| *****************************************************************************} | ||||
| 
 | ||||
|     const | ||||
|       simm16lo =  -32768; | ||||
|       simm16hi =   32767; | ||||
| 
 | ||||
| {***************************************************************************** | ||||
|                                   Helpers | ||||
| *****************************************************************************} | ||||
| 
 | ||||
|     function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE} | ||||
|     function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE} | ||||
| 
 | ||||
|     { Returns the tcgsize corresponding with the size of reg.} | ||||
|     function reg_cgsize(const reg: tregister) : tcgsize; | ||||
|     function cgsize2subreg(regtype: tregistertype; s:tcgsize):tsubregister; | ||||
| @ -309,6 +319,10 @@ unit cpubase; | ||||
|     function std_regnum_search(const s:string):Tregister; | ||||
|     function std_regname(r:Tregister):string; | ||||
| 
 | ||||
|     var | ||||
|       STK2_dummy: aint; | ||||
|       STK2_Localsize: aint; | ||||
| 
 | ||||
|   implementation | ||||
| 
 | ||||
|     uses | ||||
| @ -386,6 +400,12 @@ unit cpubase; | ||||
|       end; | ||||
| 
 | ||||
| 
 | ||||
|     function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE} | ||||
|       begin | ||||
|         result := c1 = c2; | ||||
|       end; | ||||
| 
 | ||||
| 
 | ||||
|     function std_regnum_search(const s:string):Tregister; | ||||
|       begin | ||||
|         result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)]; | ||||
| @ -404,4 +424,7 @@ unit cpubase; | ||||
|       end; | ||||
| 
 | ||||
| 
 | ||||
| begin | ||||
|   STK2_dummy := 10; | ||||
|   STK2_Localsize := 0; | ||||
| end. | ||||
|  | ||||
							
								
								
									
										246
									
								
								compiler/mips/cpugas.pas
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										246
									
								
								compiler/mips/cpugas.pas
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,246 @@ | ||||
| { | ||||
|     Copyright (c) 1999-2009 by Florian Klaempfl and David Zhang | ||||
| 
 | ||||
|     This unit implements an asmoutput class for MIPS assembly syntax | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program; if not, write to the Free Software | ||||
|     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
| 
 | ||||
|  **************************************************************************** | ||||
| } | ||||
| unit cpugas; | ||||
| 
 | ||||
| {$i fpcdefs.inc} | ||||
| 
 | ||||
| interface | ||||
| 
 | ||||
| uses | ||||
|   cpubase, | ||||
|   aasmtai, aasmcpu, assemble, aggas; | ||||
| 
 | ||||
| type | ||||
|   TGasMIPSEL = class(TGnuAssembler) | ||||
|     procedure WriteInstruction(hp: Tai); override; | ||||
|   end; | ||||
| 
 | ||||
| implementation | ||||
| 
 | ||||
| uses | ||||
|   cutils, systems, | ||||
|   verbose, itcpugas, cgbase, cgutils; | ||||
| 
 | ||||
| function GetReferenceString(var ref: TReference): string; | ||||
| begin | ||||
|   GetReferenceString := ''; | ||||
|   with ref do | ||||
|   begin | ||||
|     if (base = NR_NO) and (index = NR_NO) then | ||||
|     begin | ||||
|       if assigned(symbol) then | ||||
|         GetReferenceString := symbol.Name; | ||||
|       if offset > 0 then | ||||
|         GetReferenceString := GetReferenceString + '+' + ToStr(offset) | ||||
|       else if offset < 0 then | ||||
|         GetReferenceString := GetReferenceString + ToStr(offset); | ||||
|       case refaddr of | ||||
|         addr_hi: | ||||
|           GetReferenceString := '%hi(' + GetReferenceString + ')'; | ||||
|         addr_lo: | ||||
|           GetReferenceString := '%lo(' + GetReferenceString + ')'; | ||||
|       end; | ||||
|     end | ||||
|     else | ||||
|     begin | ||||
| {$ifdef extdebug} | ||||
|       if assigned(symbol) and | ||||
|         not(refaddr in [addr_pic,addr_lo]) then | ||||
|         internalerror(2003052601); | ||||
| {$endif extdebug} | ||||
|       if base <> NR_NO then | ||||
|         GetReferenceString := GetReferenceString + '(' + gas_regname(base) + ')'; | ||||
|       if index = NR_NO then | ||||
|       begin | ||||
|         if offset <> 0 then | ||||
|           GetReferenceString := ToStr(offset) + GetReferenceString; | ||||
|         if assigned(symbol) then | ||||
|         begin | ||||
|           if refaddr = addr_lo then | ||||
|             GetReferenceString := '%lo(' + symbol.Name + ')' + GetReferenceString | ||||
|           else | ||||
|             GetReferenceString := symbol.Name + {'+' +} GetReferenceString; | ||||
|         end; | ||||
|       end | ||||
|       else | ||||
|       begin | ||||
| {$ifdef extdebug} | ||||
|                     if (Offset<>0) or assigned(symbol) then | ||||
|                       internalerror(2003052603); | ||||
| {$endif extdebug} | ||||
|         GetReferenceString := GetReferenceString + '(' + gas_regname(index) + ')'; | ||||
| 
 | ||||
|       end; | ||||
|     end; | ||||
|   end; | ||||
| end; | ||||
| 
 | ||||
| 
 | ||||
| function getopstr(const Oper: TOper): string; | ||||
| begin | ||||
|   with Oper do | ||||
|     case typ of | ||||
|       top_reg: | ||||
|         getopstr := gas_regname(reg); | ||||
|       top_const: | ||||
|         getopstr := tostr(longint(val)); | ||||
|       top_ref: | ||||
|         if (oper.ref^.refaddr in [addr_no, addr_pic]) or ((oper.ref^.refaddr = addr_lo) and ((oper.ref^.base <> NR_NO) or | ||||
|           (oper.ref^.index <> NR_NO))) then | ||||
|           getopstr := getreferencestring(ref^) | ||||
|         else | ||||
|           getopstr := getreferencestring(ref^); | ||||
|       else | ||||
|         internalerror(10001); | ||||
|     end; | ||||
| end; | ||||
| 
 | ||||
| function getopstr_4(const Oper: TOper): string; | ||||
| var | ||||
|   tmpref: treference; | ||||
| begin | ||||
|   with Oper do | ||||
|     case typ of | ||||
|       top_ref: | ||||
|       begin | ||||
|         tmpref := ref^; | ||||
|         Inc(tmpref.offset, 4); | ||||
|         getopstr_4 := getreferencestring(tmpref); | ||||
|       end; | ||||
|       else | ||||
|         internalerror(2007050403); | ||||
|     end; | ||||
| end; | ||||
| 
 | ||||
| 
 | ||||
| procedure TGasMIPSEL.WriteInstruction(hp: Tai); | ||||
| var | ||||
|   Op: TAsmOp; | ||||
|   s,s1:  string; | ||||
|   i:  integer; | ||||
|   tmpfpu: string; | ||||
|   tmpfpu_len: longint; | ||||
| begin | ||||
|   if hp.typ <> ait_instruction then | ||||
|     exit; | ||||
|   op := taicpu(hp).opcode; | ||||
| 
 | ||||
|   case op of | ||||
|     A_P_STK2: | ||||
|     begin | ||||
|       s1 := getopstr(taicpu(hp).oper[2]^); | ||||
|       STK2_LocalSize := align(STK2_LocalSize, 8); | ||||
|       if s1[1] = '-' then | ||||
|         str(-STK2_LocalSize, s1) | ||||
|       else | ||||
|         str(STK2_LocalSize, s1); | ||||
|       s := #9 + std_op2str[A_ADDIU] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[1]^) + ',' + s1; | ||||
|       AsmWriteLn(s); | ||||
|     end; | ||||
|     A_P_FRAME: | ||||
|     begin | ||||
|     end; | ||||
|     A_P_SET_MACRO: | ||||
|     begin | ||||
|       s := #9 + '.set' + #9 + 'macro'; | ||||
|       AsmWriteLn(s); | ||||
|     end; | ||||
|     A_P_SET_REORDER: | ||||
|     begin | ||||
|       s := #9 + '.set' + #9 + 'reorder'; | ||||
|       AsmWriteLn(s); | ||||
|     end; | ||||
|     A_P_SET_NOMACRO: | ||||
|     begin | ||||
|       s := #9 + '.set' + #9 + 'nomacro'; | ||||
|       AsmWriteLn(s); | ||||
|     end; | ||||
|     A_P_SET_NOREORDER: | ||||
|     begin | ||||
|       s := #9 + '.set' + #9 + 'noreorder'; | ||||
|       AsmWriteLn(s); | ||||
|     end; | ||||
|     A_P_SW: | ||||
|     begin | ||||
|       s := #9 + std_op2str[A_SW] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')'; | ||||
|       AsmWriteLn(s); | ||||
|     end; | ||||
|     A_P_LW: | ||||
|     begin | ||||
|       s := #9 + std_op2str[A_LW] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')'; | ||||
|       AsmWriteLn(s); | ||||
|     end; | ||||
|     A_LDC1: | ||||
|     begin | ||||
|       tmpfpu := getopstr(taicpu(hp).oper[0]^); | ||||
|       s := #9 + std_op2str[A_LWC1] + #9 + tmpfpu + ',' + getopstr(taicpu(hp).oper[1]^); // + '(' + getopstr(taicpu(hp).oper[1]^) + ')'; | ||||
|       AsmWriteLn(s); | ||||
| 
 | ||||
|       tmpfpu_len := length(tmpfpu); | ||||
|       tmpfpu[tmpfpu_len] := succ(tmpfpu[tmpfpu_len]); | ||||
|       s := #9 + std_op2str[A_LWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); // + '(' + getopstr(taicpu(hp).oper[1]^) + ')'; | ||||
|       AsmWriteLn(s); | ||||
|     end; | ||||
|     A_SDC1: | ||||
|     begin | ||||
|       tmpfpu := getopstr(taicpu(hp).oper[0]^); | ||||
|       s := #9 + std_op2str[A_SWC1] + #9 + tmpfpu + ',' + getopstr(taicpu(hp).oper[1]^); //+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')'; | ||||
|       AsmWriteLn(s); | ||||
| 
 | ||||
|       tmpfpu_len := length(tmpfpu); | ||||
|       tmpfpu[tmpfpu_len] := succ(tmpfpu[tmpfpu_len]); | ||||
|       s := #9 + std_op2str[A_SWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); //+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')'; | ||||
|       AsmWriteLn(s); | ||||
|     end; | ||||
|     else | ||||
|     begin | ||||
|       s := #9 + std_op2str[op] + cond2str[taicpu(hp).condition]; | ||||
|       if taicpu(hp).delayslot_annulled then | ||||
|         s := s + ',a'; | ||||
|       if taicpu(hp).ops > 0 then | ||||
|       begin | ||||
|         s := s + #9 + getopstr(taicpu(hp).oper[0]^); | ||||
|         for i := 1 to taicpu(hp).ops - 1 do | ||||
|           s := s + ',' + getopstr(taicpu(hp).oper[i]^); | ||||
|       end; | ||||
|       AsmWriteLn(s); | ||||
|     end; | ||||
|   end; | ||||
| end; | ||||
| 
 | ||||
| 
 | ||||
| const | ||||
|   as_MIPSEL_as_info: tasminfo = | ||||
|     ( | ||||
|     id: as_gas; | ||||
|     idtxt: 'AS'; | ||||
|     asmbin: 'as'; | ||||
|     asmcmd: '-mips2 -W -EL -o $OBJ $ASM'; | ||||
|     supported_target: system_any; | ||||
|     flags: [af_allowdirect, af_needar, af_smartlink_sections]; | ||||
|     labelprefix: '.L'; | ||||
|     comment: '# '; | ||||
|     ); | ||||
| 
 | ||||
| begin | ||||
|   RegisterAssembler(as_MIPSEL_as_info, TGasMIPSEL); | ||||
| end. | ||||
							
								
								
									
										41
									
								
								compiler/mips/cpunode.pas
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								compiler/mips/cpunode.pas
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | ||||
| {****************************************************************************** | ||||
|     Copyright (c) 2000 by Florian Klaempfl | ||||
| 
 | ||||
|     Includes the MIPS code generator | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program; if not, write to the Free Software | ||||
|     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
| 
 | ||||
|  *****************************************************************************} | ||||
| unit CpuNode; | ||||
| 
 | ||||
| {$I fpcdefs.inc} | ||||
| 
 | ||||
| interface | ||||
| { This unit is used to define the specific CPU implementations. All needed | ||||
| actions are included in the INITALIZATION part of these units. This explains | ||||
| the behaviour of such a unit having just a USES clause! } | ||||
| 
 | ||||
| implementation | ||||
| 
 | ||||
|   uses | ||||
|     { generic nodes } | ||||
|     ncgbas,ncgld,ncgflw,ncgcnv,ncgmem,ncgcon,ncgcal,ncgset,ncginl,ncgopt,ncgmat,ncgobjc, | ||||
|     { to be able to only parts of the generic code, | ||||
|       the processor specific nodes must be included | ||||
|       after the generic one (FK) | ||||
|     } | ||||
|     ncpuadd,ncpucall,ncpumat,ncpuinln,ncpucnv,ncpuset; | ||||
| 
 | ||||
| end. | ||||
							
								
								
									
										598
									
								
								compiler/mips/ncpuadd.pas
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										598
									
								
								compiler/mips/ncpuadd.pas
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,598 @@ | ||||
| { | ||||
|     Copyright (c) 2000-2009 by Florian Klaempfl and David Zhang | ||||
| 
 | ||||
|     Code generation for add nodes on the FVM32 | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program; if not, write to the Free Software | ||||
|     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
| 
 | ||||
|  **************************************************************************** | ||||
| } | ||||
| unit ncpuadd; | ||||
| 
 | ||||
| {$i fpcdefs.inc} | ||||
| 
 | ||||
| interface | ||||
| 
 | ||||
| uses | ||||
|   node, ncgadd, cpubase, aasmbase, cgbase; | ||||
| 
 | ||||
| type | ||||
|   tmipsaddnode = class(tcgaddnode) | ||||
|   private | ||||
|     function cmp64_lt(left_reg, right_reg: TRegister64): TRegister; | ||||
|     function cmp64_le(left_reg, right_reg: TRegister64): TRegister; | ||||
|     function cmp64_eq(left_reg, right_reg: TRegister64): TRegister; | ||||
|     function cmp64_ne(left_reg, right_reg: TRegister64): TRegister; | ||||
|     function cmp64_ltu(left_reg, right_reg: TRegister64): TRegister; | ||||
|     function cmp64_leu(left_reg, right_reg: TRegister64): TRegister; | ||||
| 
 | ||||
|     function GetRes_register(unsigned: boolean; this_reg, left_reg, right_reg: TRegister): TRegister; | ||||
|     function GetRes64_register(unsigned: boolean; {this_reg,} left_reg, right_reg: TRegister64): TRegister; | ||||
|   protected | ||||
|     procedure second_addfloat; override; | ||||
|     procedure second_cmpfloat; override; | ||||
|     procedure second_cmpboolean; override; | ||||
|     procedure second_cmpsmallset; override; | ||||
|     procedure second_cmp64bit; override; | ||||
|     procedure second_cmpordinal; override; | ||||
|   end; | ||||
| 
 | ||||
| implementation | ||||
| 
 | ||||
| uses | ||||
|   systems, | ||||
|   cutils, verbose, | ||||
|   paramgr, | ||||
|   aasmtai, aasmcpu, aasmdata, | ||||
|   defutil, | ||||
|   {cgbase,} cgcpu, cgutils, | ||||
|   cpupara, | ||||
|   ncon, nset, nadd, | ||||
|   ncgutil, cgobj; | ||||
| 
 | ||||
| {***************************************************************************** | ||||
|                                tmipsaddnode | ||||
| *****************************************************************************} | ||||
| function tmipsaddnode.GetRes_register(unsigned: boolean; this_reg, left_reg, right_reg: TRegister): TRegister; | ||||
| var | ||||
|   tmp_asm_op: tasmop; | ||||
| begin | ||||
|   case NodeType of | ||||
|     equaln: | ||||
|       tmp_asm_op := A_SEQ; | ||||
|     unequaln: | ||||
|       tmp_asm_op := A_SNE; | ||||
|     else | ||||
|       if not (unsigned) then | ||||
|       begin | ||||
|         if nf_swapped in flags then | ||||
|           case NodeType of | ||||
|             ltn: | ||||
|               tmp_asm_op := A_SGT; | ||||
|             lten: | ||||
|               tmp_asm_op := A_SGE; | ||||
|             gtn: | ||||
|               tmp_asm_op := A_SLT; | ||||
|             gten: | ||||
|               tmp_asm_op := A_SLE; | ||||
|           end | ||||
|         else | ||||
|           case NodeType of | ||||
|             ltn: | ||||
|               tmp_asm_op := A_SLT; | ||||
|             lten: | ||||
|               tmp_asm_op := A_SLE; | ||||
|             gtn: | ||||
|               tmp_asm_op := A_SGT; | ||||
|             gten: | ||||
|               tmp_asm_op := A_SGE; | ||||
|           end; | ||||
|       end | ||||
|       else | ||||
|       begin | ||||
|         if nf_swapped in Flags then | ||||
|           case NodeType of | ||||
|             ltn: | ||||
|               tmp_asm_op := A_SGTU; | ||||
|             lten: | ||||
|               tmp_asm_op := A_SGEU; | ||||
|             gtn: | ||||
|               tmp_asm_op := A_SLTU; | ||||
|             gten: | ||||
|               tmp_asm_op := A_SLEU; | ||||
|           end | ||||
|         else | ||||
|           case NodeType of | ||||
|             ltn: | ||||
|               tmp_asm_op := A_SLTU; | ||||
|             lten: | ||||
|               tmp_asm_op := A_SLEU; | ||||
|             gtn: | ||||
|               tmp_asm_op := A_SGTU; | ||||
|             gten: | ||||
|               tmp_asm_op := A_SGEU; | ||||
|           end; | ||||
|       end; | ||||
|   end; | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(tmp_asm_op, this_reg, left_reg, right_reg)); | ||||
|   GetRes_register := this_reg; | ||||
| end; | ||||
| 
 | ||||
| function tmipsaddnode.cmp64_eq(left_reg, right_reg: TRegister64): TRegister; | ||||
| var | ||||
|   lfcmp64_L4: tasmlabel; | ||||
| begin | ||||
| 
 | ||||
|   objectlibrary.getlabel(lfcmp64_L4); | ||||
| 
 | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0)); | ||||
| 
 | ||||
|   current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, left_reg.reghi, right_reg.reghi, lfcmp64_L4)); | ||||
|   current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_sym(A_BNE, left_reg.reglo, right_reg.reglo, lfcmp64_L4)); | ||||
|   current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
| 
 | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 1)); | ||||
| 
 | ||||
|   cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L4); | ||||
|   cmp64_eq := NR_TCR10; | ||||
| end; | ||||
| 
 | ||||
| function tmipsaddnode.cmp64_ne(left_reg, right_reg: TRegister64): TRegister; | ||||
| var | ||||
|   lfcmp64_L4: tasmlabel; | ||||
| begin | ||||
| 
 | ||||
|   objectlibrary.getlabel(lfcmp64_L4); | ||||
| 
 | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 1)); | ||||
| 
 | ||||
|   current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, left_reg.reghi, right_reg.reghi, lfcmp64_L4)); | ||||
|   current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_sym(A_BNE, left_reg.reglo, right_reg.reglo, lfcmp64_L4)); | ||||
|   current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
| 
 | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0)); | ||||
| 
 | ||||
|   cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L4); | ||||
|   cmp64_ne := NR_TCR10; | ||||
| end; | ||||
| 
 | ||||
| function tmipsaddnode.cmp64_lt(left_reg, right_reg: TRegister64): TRegister; | ||||
| var | ||||
|   lfcmp64_L4, lfcmp64_L5: tasmlabel; | ||||
| begin | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0)); | ||||
| 
 | ||||
|   objectlibrary.getlabel(lfcmp64_L4); | ||||
|   objectlibrary.getlabel(lfcmp64_L5); | ||||
| 
 | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLT, NR_TCR11, left_reg.reghi, right_reg.reghi)); | ||||
|   current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L5)); | ||||
|   current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
|   current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, left_reg.reghi, right_reg.reghi, lfcmp64_L4)); | ||||
|   current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR11, left_reg.reglo, right_reg.reglo)); | ||||
|   current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L5)); | ||||
|   current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
|   current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_B, lfcmp64_L4)); | ||||
|   current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
| 
 | ||||
|   cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L5); | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 1)); | ||||
| 
 | ||||
|   cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L4); | ||||
|   cmp64_lt := NR_TCR10; | ||||
| end; | ||||
| 
 | ||||
| function tmipsaddnode.cmp64_le(left_reg, right_reg: TRegister64): TRegister; | ||||
| var | ||||
|   lfcmp64_L4, lfcmp64_L5: tasmlabel; | ||||
| begin | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0)); | ||||
| 
 | ||||
|   objectlibrary.getlabel(lfcmp64_L4); | ||||
|   objectlibrary.getlabel(lfcmp64_L5); | ||||
| 
 | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLT, NR_TCR11, right_reg.reghi, left_reg.reghi)); | ||||
|   current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L4)); | ||||
|   current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
|   current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, right_reg.reghi, left_reg.reghi, lfcmp64_L5)); | ||||
|   current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR11, right_reg.reglo, left_reg.reglo)); | ||||
|   current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L4)); | ||||
|   current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
| 
 | ||||
|   cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L5); | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 1)); | ||||
| 
 | ||||
|   cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L4); | ||||
|   cmp64_le := NR_TCR10; | ||||
| end; | ||||
| 
 | ||||
| function tmipsaddnode.cmp64_ltu(left_reg, right_reg: TRegister64): TRegister; | ||||
| var | ||||
|   lfcmp64_L4, lfcmp64_L5: tasmlabel; | ||||
| begin | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0)); | ||||
| 
 | ||||
|   objectlibrary.getlabel(lfcmp64_L4); | ||||
|   objectlibrary.getlabel(lfcmp64_L5); | ||||
| 
 | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR11, left_reg.reghi, right_reg.reghi)); | ||||
|   current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L5)); | ||||
|   current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
|   current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, left_reg.reghi, right_reg.reghi, lfcmp64_L4)); | ||||
|   current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR11, left_reg.reglo, right_reg.reglo)); | ||||
|   current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L5)); | ||||
|   current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
|   current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_B, lfcmp64_L4)); | ||||
|   current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
| 
 | ||||
|   cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L5); | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 1)); | ||||
| 
 | ||||
|   cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L4); | ||||
|   cmp64_ltu := NR_TCR10; | ||||
| end; | ||||
| 
 | ||||
| function tmipsaddnode.cmp64_leu(left_reg, right_reg: TRegister64): TRegister; | ||||
| var | ||||
|   lfcmp64_L4, lfcmp64_L5: tasmlabel; | ||||
| begin | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0)); | ||||
| 
 | ||||
|   objectlibrary.getlabel(lfcmp64_L4); | ||||
|   objectlibrary.getlabel(lfcmp64_L5); | ||||
| 
 | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR11, right_reg.reghi, left_reg.reghi)); | ||||
|   current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L4)); | ||||
|   current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
|   current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, right_reg.reghi, left_reg.reghi, lfcmp64_L5)); | ||||
|   current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR11, right_reg.reglo, left_reg.reglo)); | ||||
|   current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L4)); | ||||
|   current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
| 
 | ||||
|   cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L5); | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 1)); | ||||
| 
 | ||||
|   cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L4); | ||||
|   cmp64_leu := NR_TCR10; | ||||
| end; | ||||
| 
 | ||||
| function tmipsaddnode.GetRes64_register(unsigned: boolean; //this_reg: TRegister; | ||||
|                                                             left_reg, right_reg: TRegister64): TRegister; | ||||
| var | ||||
|   tmpreg: TRegister; | ||||
|   lfcmp64_L4, lfcmp_L5: tasmlabel; | ||||
| begin | ||||
|   case NodeType of | ||||
|     equaln: | ||||
|     begin | ||||
|       GetRes64_register := cmp64_eq(left_reg, right_reg); | ||||
|     end; | ||||
|     unequaln: | ||||
|       GetRes64_register := cmp64_ne(left_reg, right_reg); | ||||
|     else | ||||
|       if not (unsigned) then | ||||
|       begin | ||||
|         if nf_swapped in flags then | ||||
|           case NodeType of | ||||
|             ltn: | ||||
|               GetRes64_register := cmp64_lt(right_reg, left_reg); | ||||
|             lten: | ||||
|               GetRes64_register := cmp64_le(right_reg, left_reg); | ||||
|             gtn: | ||||
|               GetRes64_register := cmp64_lt(left_reg, right_reg); | ||||
|             gten: | ||||
|               GetRes64_register := cmp64_le(left_reg, right_reg); | ||||
|           end | ||||
|         else | ||||
|           case NodeType of | ||||
|             ltn: | ||||
|               GetRes64_register := cmp64_lt(left_reg, right_reg); | ||||
|             lten: | ||||
|               GetRes64_register := cmp64_le(left_reg, right_reg); | ||||
|             gtn: | ||||
|               GetRes64_register := cmp64_lt(right_reg, left_reg); | ||||
|             gten: | ||||
|               GetRes64_register := cmp64_le(right_reg, left_reg); | ||||
|           end; | ||||
|       end | ||||
|       else | ||||
|       begin | ||||
|         if nf_swapped in Flags then | ||||
|           case NodeType of | ||||
|             ltn: | ||||
|               GetRes64_register := cmp64_ltu(right_reg, left_reg); | ||||
|             lten: | ||||
|               GetRes64_register := cmp64_leu(right_reg, left_reg); | ||||
|             gtn: | ||||
|               GetRes64_register := cmp64_ltu(left_reg, right_reg); | ||||
|             gten: | ||||
|               GetRes64_register := cmp64_leu(left_reg, right_reg); | ||||
|           end | ||||
|         else | ||||
|           case NodeType of | ||||
|             ltn: | ||||
|               GetRes64_register := cmp64_ltu(left_reg, right_reg); | ||||
|             lten: | ||||
|               GetRes64_register := cmp64_leu(left_reg, right_reg); | ||||
|             gtn: | ||||
|               GetRes64_register := cmp64_ltu(right_reg, left_reg); | ||||
|             gten: | ||||
|               GetRes64_register := cmp64_leu(right_reg, left_reg); | ||||
|           end; | ||||
|       end; | ||||
|   end; | ||||
| end; | ||||
| 
 | ||||
| procedure tmipsaddnode.second_addfloat; | ||||
| var | ||||
|   op: TAsmOp; | ||||
| begin | ||||
|   pass_left_right; | ||||
|   if (nf_swapped in flags) then | ||||
|     swapleftright; | ||||
| 
 | ||||
|         { force fpureg as location, left right doesn't matter | ||||
|           as both will be in a fpureg } | ||||
|   location_force_fpureg(current_asmdata.CurrAsmList, left.location, True); | ||||
|   location_force_fpureg(current_asmdata.CurrAsmList, right.location, (left.location.loc <> LOC_CFPUREGISTER)); | ||||
| 
 | ||||
|   location_reset(location, LOC_FPUREGISTER, def_cgsize(resultdef)); | ||||
|   if left.location.loc <> LOC_CFPUREGISTER then | ||||
|     location.Register := left.location.Register | ||||
|   else | ||||
|     location.Register := right.location.Register; | ||||
| 
 | ||||
|   case nodetype of | ||||
|     addn: | ||||
|     begin | ||||
|       if location.size = OS_F64 then | ||||
|         op := A_ADD_D | ||||
|       else | ||||
|         op := A_ADD_S; | ||||
|     end; | ||||
|     muln: | ||||
|     begin | ||||
|       if location.size = OS_F64 then | ||||
|         op := A_MUL_D | ||||
|       else | ||||
|         op := A_MUL_S; | ||||
|     end; | ||||
|     subn: | ||||
|     begin | ||||
|       if location.size = OS_F64 then | ||||
|         op := A_SUB_D | ||||
|       else | ||||
|         op := A_SUB_S; | ||||
|     end; | ||||
|     slashn: | ||||
|     begin | ||||
|       if location.size = OS_F64 then | ||||
|         op := A_DIV_D | ||||
|       else | ||||
|         op := A_DIV_S; | ||||
|     end; | ||||
|     else | ||||
|       internalerror(200306014); | ||||
|   end; | ||||
|   current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op, | ||||
|     location.Register, left.location.Register, right.location.Register)); | ||||
| 
 | ||||
| end; | ||||
| 
 | ||||
| 
 | ||||
| procedure tmipsaddnode.second_cmpfloat; | ||||
| var | ||||
|   op: tasmop; | ||||
|   lfcmptrue, lfcmpfalse: tasmlabel; | ||||
| begin | ||||
|   pass_left_right; | ||||
|   if nf_swapped in flags then | ||||
|     swapleftright; | ||||
| 
 | ||||
|   { force fpureg as location, left right doesn't matter | ||||
|     as both will be in a fpureg } | ||||
|   location_force_fpureg(current_asmdata.CurrAsmList, left.location, True); | ||||
|   location_force_fpureg(current_asmdata.CurrAsmList, right.location, True); | ||||
| 
 | ||||
|   location_reset(location, LOC_REGISTER, OS_INT); | ||||
|   location.Register := NR_TCR0; | ||||
| 
 | ||||
|   case NodeType of | ||||
|     equaln: | ||||
|     begin | ||||
|       if left.location.size = OS_F64 then | ||||
|         op := A_C_EQ_D | ||||
|       else | ||||
|         op := A_C_EQ_S; | ||||
|       objectlibrary.getlabel(lfcmpfalse); | ||||
|       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR, location.Register {NR_TCR0}, NR_R0, NR_R0)); | ||||
|       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.Register, right.location.Register)); | ||||
|       current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1F, lfcmpfalse)); //lfcmpfalse | ||||
|       current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
|       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1)); | ||||
|       cg.a_label(current_asmdata.CurrAsmList, lfcmpfalse); | ||||
| 
 | ||||
|     end; | ||||
|     unequaln: | ||||
|     begin | ||||
|       if left.location.size = OS_F64 then | ||||
|         op := A_C_EQ_D | ||||
|       else | ||||
|         op := A_C_EQ_S; | ||||
|       objectlibrary.getlabel(lfcmpfalse); | ||||
|       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1)); | ||||
|       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.Register, right.location.Register)); | ||||
|       current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1F, lfcmpfalse)); | ||||
|       current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
|       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR, location.Register {NR_TCR0}, NR_R0, NR_R0)); | ||||
|       cg.a_label(current_asmdata.CurrAsmList, lfcmpfalse); | ||||
|     end; | ||||
|     ltn: | ||||
|     begin | ||||
|       if left.location.size = OS_F64 then | ||||
|         op := A_C_LT_D | ||||
|       else | ||||
|         op := A_C_LT_S; | ||||
|       objectlibrary.getlabel(lfcmptrue); | ||||
|       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1)); | ||||
|       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.Register, right.location.Register)); | ||||
|       current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1T, lfcmptrue)); | ||||
|       current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
|       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR, location.Register {NR_TCR0}, NR_R0, NR_R0)); | ||||
|       cg.a_label(current_asmdata.CurrAsmList, lfcmptrue); | ||||
|     end; | ||||
|     lten: | ||||
|     begin | ||||
|       if left.location.size = OS_F64 then | ||||
|         op := A_C_LE_D | ||||
|       else | ||||
|         op := A_C_LE_S; | ||||
|       objectlibrary.getlabel(lfcmptrue); | ||||
|       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1)); | ||||
|       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.Register, right.location.Register)); | ||||
|       current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1T, lfcmptrue)); | ||||
|       current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
|       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR, location.Register {NR_TCR0}, NR_R0, NR_R0)); | ||||
|       cg.a_label(current_asmdata.CurrAsmList, lfcmptrue); | ||||
|     end; | ||||
|     gtn: | ||||
|     begin | ||||
|       if left.location.size = OS_F64 then | ||||
|         op := A_C_LT_D | ||||
|       else | ||||
|         op := A_C_LT_S; | ||||
|       objectlibrary.getlabel(lfcmptrue); | ||||
|       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1)); | ||||
|       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, right.location.Register, left.location.Register)); | ||||
|       current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1T, lfcmptrue)); | ||||
|       current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
|       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR, location.Register {NR_TCR0}, NR_R0, NR_R0)); | ||||
|       cg.a_label(current_asmdata.CurrAsmList, lfcmptrue); | ||||
|     end; | ||||
|     gten: | ||||
|     begin | ||||
|       if left.location.size = OS_F64 then | ||||
|         op := A_C_LE_D | ||||
|       else | ||||
|         op := A_C_LE_S; | ||||
|       objectlibrary.getlabel(lfcmptrue); | ||||
|       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1)); | ||||
|       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, right.location.Register, left.location.Register)); | ||||
|       current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1T, lfcmptrue)); | ||||
|       current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP)); | ||||
|       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR, location.Register {NR_TCR0}, NR_R0, NR_R0)); | ||||
|       cg.a_label(current_asmdata.CurrAsmList, lfcmptrue); | ||||
|     end; | ||||
|   end; {case} | ||||
| end; | ||||
| 
 | ||||
| 
 | ||||
| procedure tmipsaddnode.second_cmpboolean; | ||||
| var | ||||
|   tmp_right_reg: TRegister; | ||||
| begin | ||||
|   pass_left_right; | ||||
|   force_reg_left_right(True, True); | ||||
|   tmp_right_reg := NR_NO; | ||||
|   if right.location.loc = LOC_CONSTANT then | ||||
|   begin | ||||
|     tmp_right_reg := cg.GetIntRegister(current_asmdata.CurrAsmList, OS_INT); | ||||
|     current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, tmp_right_reg, right.location.Value)); | ||||
|   end | ||||
|   else | ||||
|   begin | ||||
|     tmp_right_reg := right.location.Register; | ||||
|   end; | ||||
| 
 | ||||
|   location_reset(location, LOC_REGISTER, OS_INT); | ||||
|   location.Register := GetRes_register(True, NR_TCR0, left.location.Register, tmp_right_reg); | ||||
| 
 | ||||
| end; | ||||
| 
 | ||||
| 
 | ||||
| procedure tmipsaddnode.second_cmpsmallset; | ||||
| var | ||||
|   tmp_right_reg: TRegister; | ||||
| begin | ||||
|   pass_left_right; | ||||
|   force_reg_left_right(True, True); | ||||
| 
 | ||||
|   tmp_right_reg := NR_NO; | ||||
| 
 | ||||
|   if right.location.loc = LOC_CONSTANT then | ||||
|   begin | ||||
|     tmp_right_reg := cg.GetIntRegister(current_asmdata.CurrAsmList, OS_INT); | ||||
|     current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, tmp_right_reg, right.location.Value)); | ||||
|   end | ||||
|   else | ||||
|   begin | ||||
|     tmp_right_reg := right.location.Register; | ||||
|   end; | ||||
| 
 | ||||
| 
 | ||||
|   location_reset(location, LOC_REGISTER, OS_INT); | ||||
|   location.Register := GetRes_register(True, NR_TCR0, left.location.Register, tmp_right_reg); | ||||
| end; | ||||
| 
 | ||||
| 
 | ||||
| procedure tmipsaddnode.second_cmp64bit; | ||||
| var | ||||
|          unsigned   : boolean; | ||||
|   tmp_left_reg: TRegister; | ||||
| 
 | ||||
| begin | ||||
|           pass_left_right; | ||||
|           force_reg_left_right(false,false); | ||||
| 
 | ||||
|           unsigned:=not(is_signed(left.resultdef)) or | ||||
|                     not(is_signed(right.resultdef)); | ||||
| 
 | ||||
|   location_reset(location, LOC_REGISTER, OS_INT); | ||||
|   location.Register := GetRes64_register(unsigned, {NR_TCR0, }left.location.register64, right.location.register64); // NR_TCR0; | ||||
| end; | ||||
| 
 | ||||
| 
 | ||||
| procedure tmipsaddnode.second_cmpordinal; | ||||
| var | ||||
|   unsigned: boolean; | ||||
|   tmp_right_reg: TRegister; | ||||
| begin | ||||
|   pass_left_right; | ||||
|   force_reg_left_right(True, True); | ||||
|   unsigned := not (is_signed(left.resultdef)) or not (is_signed(right.resultdef)); | ||||
| 
 | ||||
|   tmp_right_reg := NR_NO; | ||||
|   if right.location.loc = LOC_CONSTANT then | ||||
|   begin | ||||
|     tmp_right_reg := cg.GetIntRegister(current_asmdata.CurrAsmList, OS_INT); | ||||
|     current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, tmp_right_reg, right.location.Value)); | ||||
|   end | ||||
|   else | ||||
|   begin | ||||
|     tmp_right_reg := right.location.Register; | ||||
|   end; | ||||
|   location_reset(location, LOC_REGISTER, OS_INT); | ||||
|   location.Register := getres_register(unsigned, NR_TCR0, left.location.Register, tmp_right_reg); | ||||
| end; | ||||
| 
 | ||||
| begin | ||||
|   caddnode := tmipsaddnode; | ||||
| end. | ||||
| @ -488,8 +488,10 @@ implementation | ||||
|                hregister:=cg.getintregister(list,OS_INT); | ||||
|               { load value in low register } | ||||
|               case l.loc of | ||||
| {$ifdef cpuflags} | ||||
|                 LOC_FLAGS : | ||||
|                   cg.g_flags2reg(list,OS_INT,l.resflags,hregister); | ||||
| {$endif cpuflags} | ||||
|                 LOC_JUMP : | ||||
|                   begin | ||||
|                     cg.a_label(list,current_procinfo.CurrTrueLabel); | ||||
| @ -574,8 +576,10 @@ implementation | ||||
|              hregister := l.register; | ||||
|            { load value in new register } | ||||
|            case l.loc of | ||||
| {$ifdef cpuflags} | ||||
|              LOC_FLAGS : | ||||
|                cg.g_flags2reg(list,dst_size,l.resflags,hregister); | ||||
| {$endif cpuflags} | ||||
|              LOC_JUMP : | ||||
|                begin | ||||
|                  cg.a_label(list,current_procinfo.CurrTrueLabel); | ||||
|  | ||||
| @ -1805,10 +1805,9 @@ unit rgobj; | ||||
|       end; | ||||
| 
 | ||||
| 
 | ||||
|     procedure Trgobj.do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister); | ||||
| 
 | ||||
|     var ins:Taicpu; | ||||
| 
 | ||||
|     procedure trgobj.do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister); | ||||
|       var | ||||
|         ins:Taicpu; | ||||
|       begin | ||||
|         ins:=spilling_create_load(spilltemp,tempreg); | ||||
|         add_cpu_interferences(ins); | ||||
| @ -1817,9 +1816,8 @@ unit rgobj; | ||||
| 
 | ||||
| 
 | ||||
|     procedure Trgobj.do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister); | ||||
| 
 | ||||
|     var ins:Taicpu; | ||||
| 
 | ||||
|       var | ||||
|         ins:Taicpu; | ||||
|       begin | ||||
|         ins:=spilling_create_store(tempreg,spilltemp); | ||||
|         add_cpu_interferences(ins); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 florian
						florian