fpc/compiler/powerpc/nppcset.pas
daniel 86bcea6ef5 * Code generator converted to new register notation
- Horribily outdated todo.txt removed
2003-02-19 22:00:14 +00:00

234 lines
7.3 KiB
ObjectPascal

{
$Id$
Copyright (c) 1998-2002 by Florian Klaempfl and Carl Eric Codere
Generate PowerPC assembler for in set/case nodes
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 nppcset;
{$i fpcdefs.inc}
interface
uses
node,nset,ncgset,cpubase,cginfo,cgbase,cgobj,aasmbase,aasmtai;
type
tppccasenode = class(tcgcasenode)
protected
procedure genlinearlist(hp : pcaserecord); override;
end;
implementation
uses
globtype,systems,
verbose,globals,
symconst,symdef,defutil,
paramgr,
cpuinfo,
pass_2,cgcpu,
ncon,
cga,tgobj,ncgutil,regvars,rgobj,aasmcpu;
{*****************************************************************************
TCGCASENODE
*****************************************************************************}
procedure tppccasenode.genlinearlist(hp : pcaserecord);
var
first : boolean;
last : TConstExprInt;
resflags: tresflags;
procedure genitem(t : pcaserecord);
var r:Tregister;
procedure gensub(value:longint);
var
tmpreg: tregister;
begin
value := -value;
if (value >= low(smallint)) and
(value <= high(smallint)) then
exprasmlist.concat(taicpu.op_reg_reg_const(A_ADDIC_,hregister,
hregister,value))
else
begin
tmpreg := cg.get_scratch_reg_int(exprasmlist,OS_INT);
cg.a_load_const_reg(exprasmlist,OS_INT,aword(value),tmpreg);
exprasmlist.concat(taicpu.op_reg_reg_reg(A_ADD_,hregister,
hregister,tmpreg));
cg.free_scratch_reg(exprasmlist,tmpreg);
end;
end;
begin
if assigned(t^.less) then
genitem(t^.less);
{ need we to test the first value }
if first and (t^._low>get_min_value(left.resulttype.def)) then
begin
cg.a_cmp_const_reg_label(exprasmlist,OS_INT,jmp_lt,
aword(t^._low),hregister,elselabel);
end;
if t^._low=t^._high then
begin
r.enum:=R_CR0;
if t^._low-last=0 then
exprasmlist.concat(taicpu.op_reg_reg_const(A_CMPWI,r,
hregister,0))
else
gensub(longint(t^._low-last));
last:=t^._low;
resflags.cr := R_CR0;
resflags.flag := F_EQ;
cg.a_jmp_flags(exprasmlist,resflags,t^.statement);
end
else
begin
{ it begins with the smallest label, if the value }
{ is even smaller then jump immediately to the }
{ ELSE-label }
if first then
begin
{ have we to ajust the first value ? }
if (t^._low>get_min_value(left.resulttype.def)) then
gensub(longint(t^._low));
end
else
begin
{ if there is no unused label between the last and the }
{ present label then the lower limit can be checked }
{ immediately. else check the range in between: }
gensub(longint(t^._low-last));
if (t^._low-last) <> 1 then
tcgppc(cg).a_jmp_cond(exprasmlist,jmp_lt,elselabel);
end;
gensub(longint(t^._high-t^._low));
tcgppc(cg).a_jmp_cond(exprasmlist,jmp_le,t^.statement);
last:=t^._high;
end;
first:=false;
if assigned(t^.greater) then
genitem(t^.greater);
end;
begin
{ do we need to generate cmps? }
if (with_sign and (min_label<0)) or
(opsize = OS_32) then
genlinearcmplist(hp)
else
begin
last:=0;
first:=true;
genitem(hp);
cg.a_jmp_always(exprasmlist,elselabel);
end;
end;
begin
ccasenode:=tppccasenode;
end.
{
$Log$
Revision 1.7 2003-02-19 22:00:16 daniel
* Code generator converted to new register notation
- Horribily outdated todo.txt removed
Revision 1.6 2003/01/08 18:43:58 daniel
* Tregister changed into a record
Revision 1.5 2002/11/25 17:43:28 peter
* splitted defbase in defutil,symutil,defcmp
* merged isconvertable and is_equal into compare_defs(_ext)
* made operator search faster by walking the list only once
Revision 1.4 2002/10/21 18:08:05 jonas
* some range errors fixed
Revision 1.3 2002/09/09 13:57:45 jonas
* small optimization to case genlist() case statements
Revision 1.2 2002/09/08 20:14:33 jonas
* use genlinearcmplist() for unsigned 32bit case statements instead
of genlinearlist(), because the addic. instruction always sets the
flags as if the arguments are signed 32bits (for smaller unsigned
types, this doesn't matter since they fit in s32bit)
Revision 1.1 2002/08/11 11:39:12 jonas
+ powerpc-specific genlinearlist
Revision 1.13 2002/08/11 06:14:40 florian
* fixed powerpc compilation problems
Revision 1.12 2002/08/10 17:15:12 jonas
* optimizations and bugfix
Revision 1.11 2002/07/28 09:24:18 carl
+ generic case node
Revision 1.10 2002/07/23 14:31:00 daniel
* Added internal error when asked to generate code for 'if expr in []'
Revision 1.9 2002/07/23 12:34:30 daniel
* Readded old set code. To use it define 'oldset'. Activated by default
for ppc.
Revision 1.8 2002/07/22 11:48:04 daniel
* Sets are now internally sets.
Revision 1.7 2002/07/21 16:58:20 jonas
* fixed some bugs in tcginnode.pass_2() and optimized the bit test
Revision 1.6 2002/07/20 11:57:54 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.5 2002/07/11 14:41:28 florian
* start of the new generic parameter handling
Revision 1.4 2002/07/07 10:16:29 florian
* problems with last commit fixed
Revision 1.3 2002/07/06 20:19:25 carl
+ generic set handling
Revision 1.2 2002/07/01 16:23:53 peter
* cg64 patch
* basics for currency
* asnode updates for class and interface (not finished)
Revision 1.1 2002/06/16 08:14:56 carl
+ generic sets
}