{ $Id$ Copyright (c) 1998-2002 by Florian Klaempfl This unit implements the code generator for the i386 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. **************************************************************************** } { This unit implements the code generator for the i386. } unit cgcpu; {$i fpcdefs.inc} interface uses cginfo,cgbase,cgobj,cg64f32,cgx86, aasmbase,aasmtai,aasmcpu, cpubase,cpuinfo,cpupara, node,symconst; type tcg386 = class(tcgx86) end; tcg64f386 = class(tcg64f32) procedure a_op64_ref_reg(list : taasmoutput;op:TOpCG;const ref : treference;reg : tregister64);override; procedure a_op64_reg_reg(list : taasmoutput;op:TOpCG;regsrc,regdst : tregister64);override; procedure a_op64_const_reg(list : taasmoutput;op:TOpCG;value : qword;reg : tregister64);override; procedure a_op64_const_ref(list : taasmoutput;op:TOpCG;value : qword;const ref : treference);override; private procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp); end; implementation uses globtype,globals,verbose,systems,cutils, symdef,symsym,defbase,paramgr, rgobj,tgobj,rgcpu; { ************* 64bit operations ************ } procedure tcg64f386.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp); begin case op of OP_ADD : begin op1:=A_ADD; op2:=A_ADC; end; OP_SUB : begin op1:=A_SUB; op2:=A_SBB; end; OP_XOR : begin op1:=A_XOR; op2:=A_XOR; end; OP_OR : begin op1:=A_OR; op2:=A_OR; end; OP_AND : begin op1:=A_AND; op2:=A_AND; end; else internalerror(200203241); end; end; procedure tcg64f386.a_op64_ref_reg(list : taasmoutput;op:TOpCG;const ref : treference;reg : tregister64); var op1,op2 : TAsmOp; tempref : treference; begin get_64bit_ops(op,op1,op2); list.concat(taicpu.op_ref_reg(op1,S_L,ref,reg.reglo)); tempref:=ref; inc(tempref.offset,4); list.concat(taicpu.op_ref_reg(op2,S_L,tempref,reg.reghi)); end; procedure tcg64f386.a_op64_reg_reg(list : taasmoutput;op:TOpCG;regsrc,regdst : tregister64); var op1,op2 : TAsmOp; begin get_64bit_ops(op,op1,op2); list.concat(taicpu.op_reg_reg(op1,S_L,regsrc.reglo,regdst.reglo)); list.concat(taicpu.op_reg_reg(op2,S_L,regsrc.reghi,regdst.reghi)); end; procedure tcg64f386.a_op64_const_reg(list : taasmoutput;op:TOpCG;value : qword;reg : tregister64); var op1,op2 : TAsmOp; begin case op of OP_AND,OP_OR,OP_XOR: begin cg.a_op_const_reg(list,op,lo(value),reg.reglo); cg.a_op_const_reg(list,op,hi(value),reg.reghi); end; OP_ADD, OP_SUB: begin // can't use a_op_const_ref because this may use dec/inc get_64bit_ops(op,op1,op2); list.concat(taicpu.op_const_reg(op1,S_L,lo(value),reg.reglo)); list.concat(taicpu.op_const_reg(op2,S_L,hi(value),reg.reghi)); end; else internalerror(200204021); end; end; procedure tcg64f386.a_op64_const_ref(list : taasmoutput;op:TOpCG;value : qword;const ref : treference); var op1,op2 : TAsmOp; tempref : treference; begin case op of OP_AND,OP_OR,OP_XOR: begin cg.a_op_const_ref(list,op,OS_32,lo(value),ref); tempref:=ref; inc(tempref.offset,4); cg.a_op_const_ref(list,op,OS_32,hi(value),tempref); end; OP_ADD, OP_SUB: begin get_64bit_ops(op,op1,op2); // can't use a_op_const_ref because this may use dec/inc list.concat(taicpu.op_const_ref(op1,S_L,lo(value),ref)); tempref:=ref; inc(tempref.offset,4); list.concat(taicpu.op_const_ref(op2,S_L,hi(value),tempref)); end; else internalerror(200204022); end; end; begin cg := tcg386.create; cg64 := tcg64f386.create; end. { $Log$ Revision 1.30 2002-09-07 15:25:10 peter * old logs removed and tabs fixed Revision 1.29 2002/07/20 19:28:47 florian * splitting of i386\cgcpu.pas into x86\cgx86.pas and i386\cgcpu.pas cgx86.pas will contain the common code for i386 and x86_64 Revision 1.28 2002/07/20 11:58:00 florian * types.pas renamed to defbase.pas because D6 contains a types unit so this would conflicts if D6 programms are compiled + Willamette/SSE2 instructions to assembler added Revision 1.27 2002/07/11 14:41:32 florian * start of the new generic parameter handling Revision 1.26 2002/07/07 09:52:33 florian * powerpc target fixed, very simple units can be compiled * some basic stuff for better callparanode handling, far from being finished Revision 1.25 2002/07/01 18:46:30 peter * internal linker * reorganized aasm layer Revision 1.24 2002/07/01 16:23:55 peter * cg64 patch * basics for currency * asnode updates for class and interface (not finished) Revision 1.23 2002/06/16 08:16:59 carl * bugfix of missing popecx for shift operations Revision 1.22 2002/05/22 19:02:16 carl + generic FPC_HELP_FAIL + generic FPC_HELP_DESTRUCTOR instated (original from Pierre) + generic FPC_DISPOSE_CLASS + TEST_GENERIC define Revision 1.21 2002/05/20 13:30:40 carl * bugfix of hdisponen (base must be set, not index) * more portability fixes Revision 1.20 2002/05/18 13:34:22 peter * readded missing revisions Revision 1.19 2002/05/16 19:46:50 carl + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand + try to fix temp allocation (still in ifdef) + generic constructor calls + start of tassembler / tmodulebase class cleanup Revision 1.17 2002/05/13 19:54:37 peter * removed n386ld and n386util units * maybe_save/maybe_restore added instead of the old maybe_push Revision 1.16 2002/05/12 19:59:05 carl * some small portability fixes Revision 1.15 2002/05/12 16:53:16 peter * moved entry and exitcode to ncgutil and cgobj * foreach gets extra argument for passing local data to the iterator function * -CR checks also class typecasts at runtime by changing them into as * fixed compiler to cycle with the -CR option * fixed stabs with elf writer, finally the global variables can be watched * removed a lot of routines from cga unit and replaced them by calls to cgobj * u32bit-s32bit updates for and,or,xor nodes. When one element is u32bit then the other is typecasted also to u32bit without giving a rangecheck warning/error. * fixed pascal calling method with reversing also the high tree in the parast, detected by tcalcst3 test Revision 1.14 2002/04/25 20:16:40 peter * moved more routines from cga/n386util Revision 1.13 2002/04/21 15:31:05 carl * changeregsize -> rg.makeregsize + a_jmp_always added Revision 1.12 2002/04/15 19:44:20 peter * fixed stackcheck that would be called recursively when a stack error was found * generic changeregsize(reg,size) for i386 register resizing * removed some more routines from cga unit * fixed returnvalue handling * fixed default stacksize of linux and go32v2, 8kb was a bit small :-) Revision 1.11 2002/04/04 19:06:10 peter * removed unused units * use tlocation.size in a_*loc*() routines Revision 1.10 2002/04/02 20:29:02 jonas * optimized the code generated by the a_op_const_* and a_op64_const methods Revision 1.9 2002/04/02 17:11:33 peter * tlocation,treference update * LOC_CONSTANT added for better constant handling * secondadd splitted in multiple routines * location_force_reg added for loading a location to a register of a specified size * secondassignment parses now first the right and then the left node (this is compatible with Kylix). This saves a lot of push/pop especially with string operations * adapted some routines to use the new cg methods }