{***************************************************************************** $Id$ Copyright (c) 1998-2000 by Florian Klaempfl and Peter Vreman * This code was inspired by the NASM sources The Netwide Assembler is copyright (C) 1996 Simon Tatham and Julian Hall. All rights reserved. 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 aasmcpu; {$INCLUDE fpcdefs.inc} interface uses cclasses,globals,verbose, cpuinfo,cpubase, symppu, aasmbase,aasmtai; const MaxPrefixes=4; type { alignment for operator } tai_align=class(tai_align_abstract) reg:tregister; constructor create(b:byte); constructor create_op(b:byte; _op:byte); end; taicpu = class(taicpu_abstract) opsize:topsize; constructor op_none(op:tasmop); constructor op_reg(op:tasmop;reg:tregister); constructor op_const(op:tasmop;_op1:aword); constructor op_ref(op:tasmop;const _op1:treference); constructor op_reg_reg(op:tasmop;_op1,_op2:tregister); constructor op_reg_ref(Op:TAsmOp;Reg:TRegister;const Ref:TReference); constructor op_reg_const(op:tasmop;_op1:tregister;_op2:aword); constructor op_const_reg(op:tasmop;_op1:aword;_op2:tregister); constructor op_ref_reg(Op:TAsmOp;const Ref:TReference;Reg:TRegister); constructor op_ref_ref(op:tasmop;_size:topsize;const _op1,_op2:treference); constructor op_reg_reg_reg(op:tasmop;_op1,_op2,_op3:tregister); constructor op_reg_ref_reg(op:tasmop;_op1:TRegister;_op2:TReference;_op3:tregister); constructor op_reg_const_reg(Op:TAsmOp;SrcReg:TRegister;value:aWord;DstReg:TRegister); constructor op_const_ref_reg(op:tasmop;_size:topsize;_op1:aword;const _op2:treference;_op3:tregister); constructor op_const_reg_ref(op:tasmop;_size:topsize;_op1:aword;_op2:tregister;const _op3:treference); { this is for Jmp instructions } constructor op_cond_sym(op:tasmop;cond:TAsmCond;_size:topsize;_op1:tasmsymbol); constructor op_sym(op:tasmop;_size:topsize;_op1:tasmsymbol); constructor op_sym_ofs(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint); constructor op_sym_ofs_reg(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;_op2:tregister); constructor op_sym_ofs_ref(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;const _op2:treference); procedure changeopsize(siz:topsize); private procedure init(_size:topsize);{this need to be called by all constructor} public { the next will reset all instructions that can change in pass 2 } procedure SetCondition(const c:TAsmCond); private { next fields are filled in pass1, so pass2 is faster } procedure Swatoperands; end; PROCEDURE DoneAsm; PROCEDURE InitAsm; implementation uses cutils, CpuGas; const _size=S_SW;{To be removed soon} {**************************************************************************** TAI_ALIGN ****************************************************************************} constructor tai_align.create(b:byte); begin inherited create(b); reg.enum:= R_NONE; end; constructor tai_align.create_op(b:byte; _op:byte); begin inherited create_op(b,_op); reg.enum:= R_NONE; end; {***************************************************************************** Taicpu Constructors *****************************************************************************} procedure taicpu.changeopsize(siz:topsize); begin opsize:=siz; end; procedure taicpu.init(_size:topsize); begin opsize:=_size; end; constructor taicpu.op_none(op:tasmop); begin inherited create(op); init(_size); end; constructor taicpu.op_reg(op:tasmop;reg:tregister); begin inherited create(op); init(_size); ops:=1; loadreg(0,reg); end; constructor taicpu.op_const(op:tasmop;_op1:aword); begin inherited create(op); init(_size); ops:=1; loadconst(0,aword(_op1)); end; constructor taicpu.op_ref(op:tasmop;const _op1:treference); begin inherited create(op); init(_size); ops:=1; loadref(0,_op1); end; constructor taicpu.op_reg_reg(op:tasmop;_op1,_op2:tregister); begin inherited create(op); init(_size); ops:=2; loadreg(0,_op1); loadreg(1,_op2); end; constructor taicpu.op_reg_const(op:tasmop;_op1:tregister; _op2:aword); begin inherited create(op); init(_size); ops:=2; loadreg(0,_op1); loadconst(1,aword(_op2)); end; constructor taicpu.op_reg_ref(Op:TAsmOp;Reg:TRegister;const Ref:TReference); begin if not(Op in [A_STB..A_STDFQ]) then fail; inherited Create(Op); init(_size); ops:=2; LoadReg(0,Reg); LoadRef(1,Ref); end; constructor taicpu.op_const_reg(op:tasmop;_op1:aword;_op2:tregister); begin inherited create(op); init(_size); ops:=2; loadconst(0,aword(_op1)); loadreg(1,_op2); end; constructor TAiCpu.op_ref_reg(Op:TAsmOp;const Ref:TReference;Reg:TRegister); begin if not(Op in [A_JMPL,A_FLUSH,A_LDSB..A_LDDC,A_RETT,A_SWAP]) then InternalError(2003042900); inherited Create(Op); Init(S_SW); Ops:=2; LoadRef(0,Ref); LoadReg(1,Reg); end; constructor taicpu.op_ref_ref(op:tasmop;_size:topsize;const _op1,_op2:treference); begin inherited create(op); init(_size); ops:=2; loadref(0,_op1); loadref(1,_op2); end; constructor taicpu.op_reg_reg_reg(op:tasmop;_op1,_op2,_op3:tregister); begin inherited create(op); init(_size); ops:=3; loadreg(0,_op1); loadreg(1,_op2); loadreg(2,_op3); end; constructor taicpu.op_reg_ref_reg(op:tasmop;_op1:TRegister;_op2:TReference;_op3:tregister); begin inherited create(op); init(_size); ops:=3; loadreg(0,_op1); loadref(1,_op2); loadreg(2,_op3); end; constructor taicpu.op_reg_const_reg(op:TAsmOp;SrcReg:TRegister;Value:aWord;DstReg:TRegister); begin inherited Create(Op); Init(S_W); ops:=3; LoadReg(0,SrcReg); LoadConst(1,Value); LoadReg(2,DstReg); end; constructor taicpu.op_const_ref_reg(op:tasmop;_size:topsize;_op1:aword;const _op2:treference;_op3:tregister); begin inherited create(op); init(_size); ops:=3; loadconst(0,aword(_op1)); loadref(1,_op2); loadreg(2,_op3); end; constructor taicpu.op_const_reg_ref(op:tasmop;_size:topsize;_op1:aword;_op2:tregister;const _op3:treference); begin inherited create(op); init(_size); ops:=3; loadconst(0,aword(_op1)); loadreg(1,_op2); loadref(2,_op3); end; constructor taicpu.op_cond_sym(op:tasmop;cond:TAsmCond;_size:topsize;_op1:tasmsymbol); begin inherited create(op); init(_size); condition:=cond; ops:=1; loadsymbol(0,_op1,0); end; constructor taicpu.op_sym(op:tasmop;_size:topsize;_op1:tasmsymbol); begin inherited create(op); init(_size); ops:=1; loadsymbol(0,_op1,0); end; constructor taicpu.op_sym_ofs(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint); begin inherited create(op); init(_size); ops:=1; loadsymbol(0,_op1,_op1ofs); end; constructor taicpu.op_sym_ofs_reg(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;_op2:tregister); begin inherited create(op); init(_size); ops:=2; loadsymbol(0,_op1,_op1ofs); loadreg(1,_op2); end; constructor taicpu.op_sym_ofs_ref(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;const _op2:treference); begin inherited create(op); init(_size); ops:=2; loadsymbol(0,_op1,_op1ofs); loadref(1,_op2); end; procedure taicpu.Swatoperands; var p:TOper; begin { Fix the operands which are in AT&T style and we need them in Intel style } case ops of 2:begin { 0,1 -> 1,0 } p:=oper[0]; oper[0]:=oper[1]; oper[1]:=p; end; 3:begin { 0,1,2 -> 2,1,0 } p:=oper[0]; oper[0]:=oper[2]; oper[2]:=p; end; end; end; { This check must be done with the operand in ATT order i.e.after swapping in the intel reader but before swapping in the NASM and TASM writers PM } {***************************************************************************** Assembler *****************************************************************************} procedure TAiCpu.SetCondition(const c:TAsmCond); const AsmCond2OpCode:array[TAsmCond]of TAsmOp= (A_BN,A_BNE,A_BE,A_BG,A_BLE,A_BGE,A_BL,A_BGU,A_BLEU,A_BCC, A_BCS,A_BPOS,A_NEG,A_BVC,A_BVS,A_BA,A_BNE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE); begin inherited SetCondition(c); if Opcode=A_BA then begin is_jmp:=true; Opcode:=AsmCond2OpCode[c]; {$IFDEF EXTDEBUG} WriteLn('In TAiCpu.SetCondition TAsmCond=',cond2str[c],'==>',std_op2str[OpCode]); {$ENDIF EXTDEBUG} end; end; procedure DoneAsm; begin end; procedure InitAsm; begin end; end. { $Log$ Revision 1.26 2003-05-28 23:18:31 florian * started to fix and clean up the sparc port Revision 1.25 2003/05/07 11:45:02 mazen - removed unused code Revision 1.24 2003/05/07 11:28:26 mazen - method CheckNonCommutativeOpcode removed as not used Revision 1.23 2003/05/06 20:27:43 mazen * A_BI changed to A_BL Revision 1.22 2003/05/06 15:00:36 mazen - non used code removed to bring up with powerpc changes Revision 1.21 2003/04/29 11:06:15 mazen * test of invalid opcode/operand combination gives internal error Revision 1.20 2003/04/28 09:40:47 mazen * Debug message in SetCondition more explicit. Revision 1.19 2003/03/15 22:51:58 mazen * remaking sparc rtl compile Revision 1.18 2003/03/10 21:59:54 mazen * fixing index overflow in handling new registers arrays. Revision 1.17 2003/02/18 22:00:20 mazen * asm condition generation modified by TAiCpu.SetCondition Revision 1.16 2003/01/08 18:43:58 daniel * Tregister changed into a record Revision 1.15 2003/01/05 21:32:35 mazen * fixing several bugs compiling the RTL Revision 1.14 2002/12/14 15:02:03 carl * maxoperands -> max_operands (for portability in rautils.pas) * fix some range-check errors with loadconst + add ncgadd unit to m68k * some bugfix of a_param_reg with LOC_CREFERENCE Revision 1.13 2002/11/17 16:32:04 carl * memory optimization (3-4%) : cleanup of tai fields, cleanup of tdef and tsym fields. * make it work for m68k Revision 1.12 2002/11/10 19:07:46 mazen * SPARC calling mechanism almost OK (as in GCC./mppcsparc ) Revision 1.11 2002/11/06 11:31:24 mazen * op_reg_reg_reg don't need any more a TOpSize parameter Revision 1.10 2002/11/05 16:15:00 mazen *** empty log message *** Revision 1.9 2002/10/28 20:59:17 mazen * TOpSize values changed S_L --> S_SW Revision 1.8 2002/10/22 13:43:01 mazen - cga.pas redueced to an empty unit Revision 1.7 2002/10/20 19:01:38 mazen + op_raddr_reg and op_caddr_reg added to fix functions prologue Revision 1.6 2002/10/19 20:35:07 mazen * carl's patch applied Revision 1.5 2002/10/15 09:00:28 mazen * sone coding style modified Revision 1.4 2002/10/13 21:46:07 mazen * assembler output format fixed }